答:
Some functional languages such as OCaml have built-in mechanisms to implement abstract data types therefore enforcing some invariants.  Languages which do not have such mechanisms rely on the user “not looking under the carpet” to enforce the invariants.

Abstract data types in OCaml

In OCaml, modules are used to structure a program. A module has an implementation and a signature, the latter being a kind of summary of values and types defined in the module, while the former provides the actual definitions. This can be loosely compared to the diptych .c/.h familiar to C programmers.

As an example, we can implement the Fraction module like this:

```<code># module Fraction = struct
  type t = Fraction of int * int
  let rec gcd a b =
    match a mod b with
    | 0 -> b
    | r -> gcd b r

  let make a b =
   if b = 0 then
     invalid_arg "Fraction.make"
   else let d = gcd (abs a) (abs b) in
     Fraction(a/d, b/d)

  let to_string (Fraction(a,b)) =
    Printf.sprintf "Fraction(%d,%d)" a b

  let add (Fraction(a1,b1)) (Fraction(a2,b2)) =
    make (a1*b2 + a2*b1) (b1*b2)

  let mult (Fraction(a1,b1)) (Fraction(a2,b2)) =
    make (a1*a2) (b1*b2)
end;;

module Fraction :
  sig
    type t = Fraction of int * int
    val gcd : int -> int -> int
    val make : int -> int -> t
    val to_string : t -> string
    val add : t -> t -> t
    val mult : t -> t -> t
  end
</code>```

This definition can now be used like this:

```<code># Fraction.add (Fraction.make 8 6) (Fraction.make 14 21);;
- : Fraction.t = Fraction.Fraction (2, 1)
</code>```

Anyone can produce values of the type fraction directly, bypassing the safety net built in Fraction.make:

```<code># Fraction.Fraction(0,0);;
- : Fraction.t = Fraction.Fraction (0, 0)
</code>```

To prevent this, it is possible to hide the concrete definition of the type Fraction.t like that:

```<code># module AbstractFraction : sig
  type t
  val make : int -> int -> t
  val to_string : t -> string
  val add : t -> t -> t
  val mult : t -> t -> t
end = Fraction;;

module AbstractFraction :
sig
  type t
  val make : int -> int -> t
  val to_string : t -> string
  val add : t -> t -> t
  val mult : t -> t -> t
end
</code>```

The only way to create an AbstractFraction.t is to use the AbstractFraction.make function.

Abstract data types in Scheme

The Scheme language does not have the same mechanism of abstract data types as OCaml does.  It relies on the user “not looking under the carpet” to achieve encapsulation.

In Scheme, it is customary to define predicates like fraction? recognising values giving the opportunity to validate the input.  In my experience the dominant usage is to let the user validate its input, if he forges a value, rather than to validate input in each library call.

There is however several strategies to enforce abstraction of returned values, like returning a closure which yields the value when applied or returning a reference to a value in a pool managed by the library – but I never saw any of them in practice.

Body:
Some functional languages such as OCaml have built-in mechanisms to implement abstract data types therefore enforcing some invariants.  Languages which do not have such mechanisms rely on the user “not looking under the carpet” to enforce the invariants.

Abstract data types in OCaml

In OCaml, modules are used to structure a program. A module has an implementation and a signature, the latter being a kind of summary of values and types defined in the module, while the former provides the actual definitions. This can be loosely compared to the diptych .c/.h familiar to C programmers.

As an example, we can implement the Fraction module like this:

# module Fraction = struct
  type t = Fraction of int * int
  let rec gcd a b =
    match a mod b with
    | 0 -> b
    | r -> gcd b r

  let make a b =
   if b = 0 then
     invalid_arg "Fraction.make"
   else let d = gcd (abs a) (abs b) in
     Fraction(a/d, b/d)

  let to_string (Fraction(a,b)) =
    Printf.sprintf "Fraction(%d,%d)" a b

  let add (Fraction(a1,b1)) (Fraction(a2,b2)) =
    make (a1*b2 + a2*b1) (b1*b2)

  let mult (Fraction(a1,b1)) (Fraction(a2,b2)) =
    make (a1*a2) (b1*b2)
end;;

module Fraction :
  sig
    type t = Fraction of int * int
    val gcd : int -> int -> int
    val make : int -> int -> t
    val to_string : t -> string
    val add : t -> t -> t
    val mult : t -> t -> t
  end

This definition can now be used like this:

# Fraction.add (Fraction.make 8 6) (Fraction.make 14 21);;
- : Fraction.t = Fraction.Fraction (2, 1)

Anyone can produce values of the type fraction directly, bypassing the safety net built in Fraction.make:

# Fraction.Fraction(0,0);;
- : Fraction.t = Fraction.Fraction (0, 0)

To prevent this, it is possible to hide the concrete definition of the type Fraction.t like that:

# module AbstractFraction : sig
  type t
  val make : int -> int -> t
  val to_string : t -> string
  val add : t -> t -> t
  val mult : t -> t -> t
end = Fraction;;

module AbstractFraction :
sig
  type t
  val make : int -> int -> t
  val to_string : t -> string
  val add : t -> t -> t
  val mult : t -> t -> t
end

The only way to create an AbstractFraction.t is to use the AbstractFraction.make function.

Abstract data types in Scheme

The Scheme language does not have the same mechanism of abstract data types as OCaml does.  It relies on the user “not looking under the carpet” to achieve encapsulation.

In Scheme, it is customary to define predicates like fraction? recognising values giving the opportunity to validate the input.  In my experience the dominant usage is to let the user validate its input, if he forges a value, rather than to validate input in each library call.

There is however several strategies to enforce abstraction of returned values, like returning a closure which yields the value when applied or returning a reference to a value in a pool managed by the library – but I never saw any of them in practice.


问:
Blocking function call with asynchronous content
I am sure that this is a common design pattern, but I seem to have a blind-spot.

I have a requirement that the function call from Application to Service be blocking, but service needs to do something asynchronous.

Well, I can handle that, BUT, there can be multiple applications and there is only one service.

While the service should block the application, it should also be able to handle multiple parallel requests from different applications.

I suppose I need to spawn a new thread for each application’s request, but how then can I return from the thread to application at the end?

I don't mind an assembler insert to store the application’s return address & pop it later, but is that really necessary?

Do I need to do anything special in C++ to mark the service function as re-entrant?

Can someone please lift my blindfold?

[Update] There is no correlation between the applications.
Also, only the service would be allowed to spawn a thread, not the applications. So, I am thinking of a service  main spawning a bunch of service threads, but I don't see how I can can handle the function call blocking & return.

答:
You have to use a blocking construct on a per-request basis.

This is called Futures (programming)

Each request will have its own Future. Once the request processing is started (possibly in a separate pool of threads, as you have described), the caller will be blocked on the Future's fulfillment, or failure.

When the result arrives, the Future is unblocked, and the call will return to the application.

When using this pattern, one must take great care prevent deadlocks and zombies. In other words, the Future needs to be unblocked at some time, whether the result is successful or failure (and in case of failure, throwing an exception back to the application is a fair game) - the call must not just hang there indefinitely.

As to thread-pool design:

There will be at least one thread per simultaneous requester (i.e. application), which will be blocked during the request.

If the applications and the service are inside the same process, these threads are the same as the application threads, which will become blocked.

There will be a separate thread pool, requiring as many threads as is necessary to do the work between the service and the internet. These threads are in addition to the request-accepting threads.

The exact number depends on how the work is done. It is possible to use asynchronous pattern (reactor) here, which might reduce the number of threads needed, but that will not have any effect on the number of request-accepting threads.

If the request from Application to Service occurs over network, there is a decoupling between Application threads and Service threads (in other words, a blocking of an Application request does not involve a "thread" at all; just a non-response from a network connection.) In that case the Service can also use reactor pattern, which means you can further reduce the number of threads.

ContentLicense: CC BY-SA 3.0


问:
When writing a library or an API, when should and when shouldn't I validate or automatically correct errors in data provided by another developer?
I have a fairly good understanding of when data validation should and shouldn't exist when it comes when writing an application that is only dealt with by an end-user, and all the different tiers of the application and what code should check what (or, I would at least hope that I have a good idea).

However, as I've begun writing code that is not only going to interact with data provided by an end-user, but which will have developers (other than myself) specifying parameters and data to it, I've come across this conundrum numerous times. When should I validate data? When should I let it break? When is validation too little, or too comprehensive in scope? What about performance; how may it be hindered by additional layers of validation?

To provide a concrete example (out of many), one such case I had was when I was building a component that would manage a single-page web application. This component would accept a JSON object representing the web application's navigation map, in which were defined routes and the URLs at which page content resided for each route. It would use this tree of data to register the appropriate routes with a client-side Javascript router, and then handle loading and presenting pages when the right route was selected. When doing this, I encountered the following hypothetical scenario:

Developer specifies two pages in the navigation map, let's say page-1 and page-2 for example.

Developer defines page-1 to have the route #!/path.

Developer also defines (mistakenly?) page-2 to have #!/path as its route.

The problem here is that, for the two pages in the example above, there's no way for my component to determine which of the two pages to load, as both have the same route: https://localhost/my-app/#!/path leads to two entirely different pages! My component would only be aware of the last page with that registered route, as it would overwrite the definition of the first page for that route.

At first, having shortly before worked with a bunch of code related to user input validation, I added logic into the recursive function which parsed the navigation tree to maintain a list of existing routes/paths, and if a conflict was found, append an incrementing number to the end to avoid conflicts. So, for example, page-1's route would stay #!/path, but when parsing the next page, the code would note that it already encountered #!/path as a route and rename the route to #!/path-2.

I didn't think much of it at the time. But recently, as I was going back to port the code to a new format, I was looking over this part of the initialization function and I wasn't sure if it was the right thing to do.

So far, the farthest I've come to a solution to instances like these, is the thought that perhaps both methods of conquering this problem, validation and the lack thereof, have their own pros and cons.

Also, and I feel this is important to note, I'm not only talking about situations where I fix an error for a developer. I find myself in the same situation when I need to decide when to check for an error in developer-provided data that is going to another component that is encapsulated within my component. When should I let the mistake go unchecked by my code, and let the library/component I'm using throw an error on its own? When should I step in and validate the data first before relaying it over?

The pros I've thought of are:

The code continues to work even when an error is made, which may be desirable for an environment where downtime is a big problem.

A developer can use the error-correction behavior to their advantage, and rely on it as a sort of shorthand, in the sense of having to code less.

Similar to point 2, the developer doesn't have to watch their code using my API for errors/omissions/mistakes as strictly, which may fit their environment and the applications more flexibly, making it less likely for an issue to come up when using another product/component, or may just make it easier for them to manage the application if there are many similar lines of code using my API.

The cons I've thought of are:

This could lead to undesired behavior as an error could go unnoticed for a long time without throwing any errors. Depending on the circumstances, it may make finding the source of the bug tougher to find.

If developers begin relying on the error-correction mechanism I implement, that means that as more people depend on it working the way it does, the more likely it is for a new version of my element to break functionality for a lot of people. This may make improving my library/component/API tougher over time.

Additional validation logic at such a low level may potentially hinder performance. In some cases, this may not be noticeable if at small scale, but when used at larger scale, may become a significant problem.

Validation logic and error-correction logic further complicates my code. This may complicate maintenance as well, and with more moving parts, the more points of failure.

I'm not sure what's a good workflow to follow to get to a resolution in this case, and what rules/guidelines I should follow when working with such systems. I've certainly learned that developing a self-encapsulated program is much easier than developing an extensible system!

I've tried looking up information to help me figure out this problem, but so far the vast majority of what I've found relates only to working with end-user input, not developing APIs or libraries for other developers to use. With end-user-provided data, I need to be worried about my application breaking. But, in this case, I don't have that worry - instead it's the developer who wrote their own program using my library that will encounter an issue - with their program. How much should I be concerned with their application breaking due to their own mistake?

So, in conclusion:

What steps should I follow to determine, when developing APIs or extensible components, when I should or when I should not correct mistakes validate data provided by other developers?

How should I determine when my code should let 3rd-party data go unchecked to a deeper API/program component not written by me to let it throw an error, and when it should step in and check for errors first before relaying the data?

Footnote:

To be clear, I understand there isn't always (or, rather, is rarely) a one-size-fits-all solution, and I am not asking for the "best option." Really what I'm looking to understand is how do I evaluate which route to take in this case, and what variables may I be not considering? From the experience of others who have worked with similar situations, what did you learn along the way, and what should I do to figure this problem out? I'm coming at this without any practical experience working in an office or on a project team, only experience with the technology itself. The more I've developed, the more I've learned that there is far more to programming than just the code itself.

答:
I've been developing extensible software for a long time now. I've also been on the other side.
One thing I've learned is that you want libraries you use to "Fail fast". What that means is, it should break my software as soon as possible if something is wrong. If you can (which in this case I presume you can't) break at compile time. If not, throw an exception when debugging and make it as clear as possible as to what is wrong. Don't hide errors at debugging time. Then if you need to be very robust, at release time, don't thrown an exception, but do log a clear warning as to what is going on.

All this leads to a very usable, self debuggable third party library, which is what you, and any developers using your code, want.


问:
When NOT to use virtual destructors?
I believed I searched many times about virtual destructors, most mention the purpose of virtual destructors, and why you need virtual destructors. Also I think in most cases destructors need to be virtual.

Then the question is: Why doesn't c++ set all destructors virtual by default? or in other questions:

When do I NOT need to use virtual destructors?

In which case I should NOT use virtual destructors?

What is the cost of using virtual destructors if I use it even if it is not needed?

答:
Why c++ not set all destructors virtual by default?
Cost of extra storage and call of virtual method table.
C++ is used for system, low-latency, rt programming where this could be burden.

OwnerDisplayName: amuse

Title: When NOT to use virtual destructors?


答: Declaring a destructor virtual is only necessary when you plan to make your class inheritable. Usually the classes of the standard library (such as std::string) do not provide a virtual destructor and thus are not meant for subclassing.

Title: When NOT to use virtual destructors?

Body:
I believed I searched many times about virtual destructors, most mention the purpose of virtual destructors, and why you need virtual destructors. Also I think in most cases destructors need to be virtual.

Then the question is: Why doesn't c++ set all destructors virtual by default? or in other questions:

When do I NOT need to use virtual destructors?

In which case I should NOT use virtual destructors?

What is the cost of using virtual destructors if I use it even if it is not needed?

OwnerDisplayName: Constantinius


答:
If you add a virtual destructor to a class:

in most (all?) current C++ implementations, every object instance of that class needs to store a pointer to the virtual dispatch table for the runtime type, and that virtual dispatch table itself added to the executable image

the address of the virtual dispatch table is not necessarily valid across processes, which can prevent safely sharing such objects in shared memory

have an embedded virtual pointer frustrates creating a class with memory layout matching some known input or output format (for example, so a Price_Tick* could be aimed directly at suitably aligned memory in an incoming UDP packet and used to parse/access or alter the data, or placement-newing such a class to write data into an outgoing packet)

the destructor calls themselves may - under certain conditions - have to be dispatched virtually and therefore out-of-line, whereas non-virtual destructors might be inlining or optimised away if trivial or irrelevant to the caller

The "not designed to be inherited from" argument wouldn't be a practical reason for not always having a virtual destructor if it weren't also worse in a practical way as explained above; but given it is worse that's a major criterion for when to pay the cost: default to having a virtual destructor if your class is meant to be used as a base class.  That's not always necessary, but it ensures the classes in the heirarchy can be used more freely without accidental undefined behaviour if a derived class destructor is invoked using a base class pointer or reference.

"in most case destructors need to be virtual"

Not so... many classes have no such need.  There are so many examples of where it's unnecessary it feels silly to enumerate them, but just look through your Standard Library or say boost and you'll see there's a large majority of classes that don't have virtual destructors.  In boost 1.53 I count 72 virtual destructors out of 494.

Title: When NOT to use virtual destructors?

OwnerDisplayName: Tony


答:
In which case I should NOT use virtual destructors?

For a concrete class which doesn't want to be inherited.

For a base class without polymorphic deletion. Either clients should not be able to delete polymorphically using a pointer to Base.

BTW,

In which case should use virtual destructors?

For a base class with polymorphic deletion.

Title: When NOT to use virtual destructors?

OwnerDisplayName: songyuanyao

ContentLicense: CC BY-SA 4.0


答:
This is a good example of when to not use the virtual destructor:
From Scott Meyers:

If a class does not contain any virtual functions, that is often an indication that it is not meant to be used as a
base class. When a class is not intended to be used as a base class, making the destructor virtual is usually a bad
idea. Consider this example, based on a discussion in the ARM:

```<code>// class for representing 2D points
class Point {
public:
    Point(short int xCoord, short int yCoord);
    ~Point();
private:
    short int x, y;
};
</code>```

If a short int occupies 16 bits, a Point object can fit into a 32-bit register. Furthermore, a Point object can be
passed as a 32-bit quantity to functions written in other languages such as C or FORTRAN. If Point's destructor
is made virtual, however, the situation changes.

The moment you add virtual member,a  virtual pointer is added to your class that points to virtual table for that class.

Title: When NOT to use virtual destructors?

Body:
This is a good example of when to not use the virtual destructor:
From Scott Meyers:

If a class does not contain any virtual functions, that is often an indication that it is not meant to be used as a
base class. When a class is not intended to be used as a base class, making the destructor virtual is usually a bad
idea. Consider this example, based on a discussion in the ARM:

// class for representing 2D points
class Point {
public:
    Point(short int xCoord, short int yCoord);
    ~Point();
private:
    short int x, y;
};

If a short int occupies 16 bits, a Point object can fit into a 32-bit register. Furthermore, a Point object can be
passed as a 32-bit quantity to functions written in other languages such as C or FORTRAN. If Point's destructor
is made virtual, however, the situation changes.

The moment you add virtual member,a  virtual pointer is added to your class that points to virtual table for that class.

OwnerDisplayName: basav


答:
There will be an overhead in the constructor for creating the vtable (if you don't have other virtual functions, in which case you PROBABLY, but not always, should have a virtual destructor too). And if you don't have any other virtual functions, it makes your object one pointer-size larger than otherwise is necessary. Obviously, the increased size can have a big impact on small objects.

There is an extra memory read to get the vtable and then call the function indirectory through that, which is overhead over non-virtual destructor when the destructor is called. And of course, as a consequence, a little extra code generated for each call to the destructor. This is for cases where the compiler can't deduce the actual type - in those cases where it can deduce the actual type, the compiler will not use the vtable, but call the destructor directly.

You should have a virtual destructor if your class is intended as a base-class, in particular if it may be created/destroyed by some other entity than the code that knows what type it is at creation, then you need a virtual destructor.

If you are not sure, use virtual destructor. It's easier to remove virtual if it shows up as a problem than it is to try to find the bug caused by "the right destructor is not called".

In short you should not have a virtual destructor if:
 1. You don't have any virtual functions.
 2. Do not derive from the class (mark it final in C++11, that way the compiler will tell if you try to derive from it).

In most cases, creation and destruction is not a major part of the time spent using a particular object unless there is "a lot of content" (creating a 1MB string is obviously going to take some time, because at least 1MB of data needs to be copied from wherever it currently is located). Destructing a 1MB string is no worse than destruction of a 150B string, both will require deallocating the string storage, and not much else, so the time spent there is typically the same [unless it's a debug build, where deallocation often fills memory with a "poison pattern" - but that is not how you are going to run your real application in production].

In short, there is a small overhead, but for small objects, it may make a difference.

Note also that compilers can optimise away the virtual lookup in some cases, so it's only a penalty

As always when it comes to performance, memory footprint, and such: Benchmark and profile and measure, compare the results with alternatives, and look at where MOST of the time/memory is spent, and don't try to optimise the 90% of code that isn't run much [most applications have about 10% of code that is highly influential on the execution time, and 90% of code that doesn't have much influence at all]. Do this in a high optimisation level, so you already have the benefit of the compiler doing a good job! And repeat, check again and improve stepwise. Don't try to be clever and try to figure out what is important and what isn't unless you have a lot of experience with that particular type of application.

Title: When NOT to use virtual destructors?

OwnerDisplayName: Mats Petersson


问:
Lesser of two evils regarding return types
I'm implementing a system in PHP where values are represented with objects that implement an Amount interface.  I'm building two different implementations of this interface, one using a simple integer internally to represent the value being stored, and the other using GMP objects.

The interface method that's proving a sticking point is as follows:

```<code>/**
 * Get the amount being stored
 *
 * @return number
 */
public function getAmount ();
</code>```

(If you're not familiar with PHP documentation conventions, number means any type which can be considered numeric, which would mean either an integer or a float)

The idea is that in most cases the integer implementation will be used for performance and memory usage reasons, and you would only switch to the GMP implementation when number sizes start exceeding what you can put in an integer.  Overflow could be handled like this (in psuedo-code):

```<code>try
{
    $someAmount -> add ($otherAmount);
}
catch (OverFlowException $e)
{
    // Replace the overflowed Amount object with a BigAmount
    $someAmount = new BigAmount ($someAmount -> getValue ());

    // Retry the add
    $someAmount -> add ($otherAmount);
}
</code>```

My integer based implementation is very simple:

```<code>/**
 * @return integer
 */
public function getAmount ()
{
    return $this -> amount;
}
</code>```

However, as I started to implement the GMP version things started getting complicated:

```<code>/**
 * Get the amount as an integer or string
 *
 * This method will attempt to return the current value as an integer. If
 * the value being represented is beyond the range of a PHP integer then
 * it will return a string instead.
 *
 * @return number|string
 */
public function getAmount ()
{
    // If the value is within integer range then return an int
    if ((gmp_cmp ($this -> amount, PHP_INT_MAX) < 1)
    && (gmp_cmp ($this -> amount, PHP_INT_MAX * -1 - 1) > -1))
    {
        return gmp_intval ($this -> amount);
    } else {
        return gmp_strval ($this -> amount);
    }
}
</code>```

As I was implementing this, I realised it had some problems:

It doesn't always return the same type (resulting in a violation of the principle of least surprise)

It doesn't strictly conform to its interface (Also violating least surprise)

Getters are supposed to be extremely simple and this isn't

The obvious first solution was to simply return the GMP object, but that would mean that the object would never return what its interface says it should, and that this class would be returning objects instead of primitive types like the integer implementation does.

The second solution was for the getter to always return a string.  This would be only slightly more complex than returning the GMP object, and it would mean a primitive type was being returned, but we're still not conforming to the interface.

A third solution would be to have the getter throw an exception if the value can't be returned as an integer and provide an additional method for getting the value as a string.  This would fulfil the contract of the interface (if I changed the interface to indicate that an exception could be thrown if the value can't be returned as an integer), but would add an additional burden on programmers using the classes to deal with having to handle cases where numbers are too big for integers.

So in summary, I have a number of choices, none completely ideal:

Stick with the current solution, and have a method that can return different types

Have the method always return a GMP (which is not a primitive type and not the type the interface says)

Have the method always return a string (which is a primitive type but not the type the interface says)

Throw an exception if an integer can't be returned and supply an additional method for those cases (which meets the demands of the interface but would add requirements to handle it in consuming code)

Which approach would you consider to be best (or least worst), or is there another approach I've not considered?

答: In the end I decided on option 4.  Have the interface specify that getAmount() can throw an exception, and have the BigAmount implementation throw one should it not be possible to express its value as an integer.  Then I'll have another method that can return the amount in another format.  It would require the programmer using the class to jump through some additional hoops, but at least those hoops are well defined and documented.  </p>


问:
How do I show 'creates' in a UML class diagram?
Let's say my code is going to look like this:

```<code>public class MyController
{
    private Foo foo;
    private FooGenerator fooGen;

    //setters

    public void work()
    {
        this.foo = this.fooGen.generateFoo();
        System.out.println(this.foo.toString());
    }
}

public class FooGenerator()
{
    public Foo generateFoo()
    {
        String[] names = ["Andy", "Bob", "Charlie"];
        String[] colors =  ["Red", "Green", "Blue"];

        int nameIndex = new Random().nextInt(names.length);
        int colorIndex = new Random().nextInt(colors.length);

        return new Foo(names[nameIndex], colors[colorIndex], new Random().nextInt(100));
    }
}

public class Foo()
{
    private String color;
    private String name;
    private int age;

    public Foo(String color, String name, int age)
    {
        this.color = color;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString()
    {
         return "This Foo's name is " + this.name + ", color is " + this.color + ", and is " + this.age + " years old.";
    }
}
</code>```

So what we have is MyController HAS a FooGenerator, and is passed back a Foo from the FooGenerator, which MyController then utilises.

The question is, how do I represent this in a UML diagram?

答:
Chiming in: this is a very small example of the ongoing "Model-Based" vs "Model-Driven" engineering debate. The question is what is the purpose of your model?

Model-Driven - you are trying to generate your code directly from your model. This was the thesis/goal of "Executable UML" and others. If you are working in this sort of team, you will need to study the details of how your particular tool generates code because UML itself does not provide prescriptive guidance on how code should be generated.

Model-Based - you are trying to use the modeling diagrams as a communications method to create "a single version of the truth" among a (usually diverse) set of stakeholders. For example, you may have an upcoming code review? Then you need to think about your audience. Do they need this level of detail up on the screen in the conference room? If so, I agree with the other commenter above...the fact that FooGenerator creates Foo is an activity. You might look at using a sequence diagram. FooGenerator goes in one swimlane and issues a "Create" message to another swimlane that contains "Foo" ...or something like this.

Hope this helps


问:
Should I use BLOB or Tables for storing large data?
Problem

Currently investigating a solution to improve the performance of a web application. The application works well for small projects, but faces performance issues in the UI when working with large projects.

The use case is the following:

A user has to submit an excel document that contains 10000 line items. Each line item contains approximately 50 terms and each term can have one or more attributes.
The system should support a project that can handle 200 users uploading such documents.
A max of 10 users can concurrently be active. There can be multiple such large projects.

The database currently used is Oracle. We also need to ensure that the chosen solution will work well with an in-memory columnar RDBMS.

The existing functionality works well for small projects that has both a web UI and an excel interface. But the web UI has performance issues with large projects and we will solely rely on an excel interface.

The operations on the data involve upload/import, download/export, editing and reports.

All actions have to be transactional, since there are other updates within the RDBMS that occur as part of the upload. So this cannot be put in a non-transactional data source. There is at least one main operation where we need to load all the data. This operation can be done asynchronously.

Existing solution

Our existing solution which runs on tomcat and Oracle uses wide tables. This solution works well upto 1000 line items and then has performance issues on the application server.
The performance issues relate to java object hydration and causes memory issues on the application server. This is because the wide table has a large number of null columns and the java objects that are created are large due to a large number of empty fields.

Options

In order to handle a larger number of line items we need to reduce the memory footprint of the existing solution.
We are trying to decide between the following approaches:

BLOB

Narrow table

Redesigned Java object (New)

BLOB solution

One way to avoid the null values is to transform the excel document into a concise key value format that can be compressed and stored in the database as a BLOB per user.
The advantage of this approach is:

Use considerably less space in the DB.

The drawbacks are:

We are limited in what we can do, since there are some operations
that will need to process data across all users.

A small edit will cause the whole BLOB to be rewritten and thus causing redo log
growth.

Will be difficult to retrofit the existing UI against this model in the future

Maintain a new model for large projects

Narrow table

This approach solves the null values by having a few fields with a row for each term. The number of null columns is reduced drastically. The java objects hydrated from these rows do not have empty fields and can be small in size. So the memory issue is alleviated.
  The advantages are:

A narrow table is well suited for an in-memory columnar approach

Keeps open the possibility of reworking the UI to work against the new table structure

The drawbacks are:

Order of magnitude increase in the number of rows. A single project will end up having 10000x50x200 rows, i.e., 100 millions rows.

Maintain a new model since the UI will not be touched and that will go off the old model.

Redesigned java class

Had not initially considered this approach but it looks like a good option.
We use the existing data model, but revamp our java class backed by a map. Only the populated fields are held in this map. This avoids having a class with a large number of fields and hence reduces the memory footprint for a sparsely populated object.

The advantage

Solves the application memory issue with the least impact of all 3 options

Uses the existing data model

Drawbacks

Does not get rid of empty columns in the DB. But I think we can live with this for now.

May not be the best format for a columnar in-memory RDBMS

Question

What is the best approach to take?

Update
As I was clearing up the description, a potential third option (Redesigned java class) dawned on me. So I am going to investigate it further as it looks promising with no model impact. Let me know if this is not a good option based on the use case and if you see any issues with it.

答:
Yes, the big question is what do you want to do with these excel documents once they're in the DB. You can store them as BLOBS quite happily, but then you can store them as files on the filesystem too, and the latter allows you to manipulate the documents in various ways (eg running code to change them).

If you're just storing them for later retrieval, then store them as blobs. You can store additional metadata about the contents alongside the blob and this is the approach I'd use if you needed to run queries about the documents.

Note that SQL Server 2012 has the ability to index files that are stored in 'filetables' which are hybrid file/DBs so you get the benefit of both.


问:
Is it okay to go against all-caps naming for enums to make their String representation simpler?
Several times I've seen people use title-case or even all lower-case naming for enum constants, for example:

```<code>enum Color {
  red,
  yellow,
  green;
}
</code>```

This makes working with their string form simple and easy, if you want to do throw new IllegalStateException("Light should not be " + color + "."), for example.

This seems more acceptable if the enum is private, but I still don't like it.  I know I can make an enum constructor with a String field, and then override toString to return that name, like this:

```<code>enum Color {
  RED("red"),
  YELLOW("yellow"),
  GREEN("green");

  private final String name;

  private Color(String name) {
    this.name = name
  }

  @Override public String toString() {
    return name;
  }
}
</code>```

But look how much longer that is.  It's annoying to keep doing if you have a bunch small enums you want to keep simple.  Is it okay to just use unconventional case formats here?

答:
Arguably, following the UPPERCASE naming convention violates DRY.  (And YAGNI).  e.g., in at your code example #2: "RED" and "red" are repeated.

So, do you follow official convention or follow DRY?  Your call.

In my code, I will follow DRY.  However, I will put in a comment on the Enum class, saying "not all uppercase because (explanation here)"


答:
Perhaps consider a hybrid approach. Fetching and storing documents is the purview of document-centric or "NoSQL" databases. Perhaps store the actual spreadsheets in (e.g.) Cassandra and keep your metadata (and copies of any working data, if you only really care about a subset of the data in the spreadsheet) in Oracle.

As to your memory pressure in Tomcat, take a look at the Flyweight design pattern. It basically recommends that you don't create objects for every bit of data; instead only instantiate an object when you need the data. For example, instead of creating an object with 10K rows consisting of 50 items, only create as many rows as you need for the current operation, likewise with items. This will require keeping the backing data in a raw form (the Excel spreadsheet) and only instantiating the individual values when required.

Title: Should I use BLOB or Tables for storing large data?

Body:
Problem

Currently investigating a solution to improve the performance of a web application. The application works well for small projects, but faces performance issues in the UI when working with large projects.

The use case is the following:

A user has to submit an excel document that contains 10000 line items. Each line item contains approximately 50 terms and each term can have one or more attributes.
The system should support a project that can handle 200 users uploading such documents.
A max of 10 users can concurrently be active. There can be multiple such large projects.

The database currently used is Oracle. We also need to ensure that the chosen solution will work well with an in-memory columnar RDBMS.

The existing functionality works well for small projects that has both a web UI and an excel interface. But the web UI has performance issues with large projects and we will solely rely on an excel interface.

The operations on the data involve upload/import, download/export, editing and reports.

All actions have to be transactional, since there are other updates within the RDBMS that occur as part of the upload. So this cannot be put in a non-transactional data source. There is at least one main operation where we need to load all the data. This operation can be done asynchronously.

Existing solution

Our existing solution which runs on tomcat and Oracle uses wide tables. This solution works well upto 1000 line items and then has performance issues on the application server.
The performance issues relate to java object hydration and causes memory issues on the application server. This is because the wide table has a large number of null columns and the java objects that are created are large due to a large number of empty fields.

Options

In order to handle a larger number of line items we need to reduce the memory footprint of the existing solution.
We are trying to decide between the following approaches:

BLOB

Narrow table

Redesigned Java object (New)

BLOB solution

One way to avoid the null values is to transform the excel document into a concise key value format that can be compressed and stored in the database as a BLOB per user.
The advantage of this approach is:

Use considerably less space in the DB.

The drawbacks are:

We are limited in what we can do, since there are some operations
that will need to process data across all users.

A small edit will cause the whole BLOB to be rewritten and thus causing redo log
growth.

Will be difficult to retrofit the existing UI against this model in the future

Maintain a new model for large projects

Narrow table

This approach solves the null values by having a few fields with a row for each term. The number of null columns is reduced drastically. The java objects hydrated from these rows do not have empty fields and can be small in size. So the memory issue is alleviated.
  The advantages are:

A narrow table is well suited for an in-memory columnar approach

Keeps open the possibility of reworking the UI to work against the new table structure

The drawbacks are:

Order of magnitude increase in the number of rows. A single project will end up having 10000x50x200 rows, i.e., 100 millions rows.

Maintain a new model since the UI will not be touched and that will go off the old model.

Redesigned java class

Had not initially considered this approach but it looks like a good option.
We use the existing data model, but revamp our java class backed by a map. Only the populated fields are held in this map. This avoids having a class with a large number of fields and hence reduces the memory footprint for a sparsely populated object.

The advantage

Solves the application memory issue with the least impact of all 3 options

Uses the existing data model

Drawbacks

Does not get rid of empty columns in the DB. But I think we can live with this for now.

May not be the best format for a columnar in-memory RDBMS

Question

What is the best approach to take?

Update
As I was clearing up the description, a potential third option (Redesigned java class) dawned on me. So I am going to investigate it further as it looks promising with no model impact. Let me know if this is not a good option based on the use case and if you see any issues with it.


问:
Where should my team start with becoming "modern"?
I'm a relatively new developer, fresh from college. While in college and during subsequent job-seeking, I realized that there were a lot of "modern" software development methodologies that my education was lacking: unit testing, logging, database normalization, agile development (vs. generic agile concepts), coding style guides, refactoring, code reviews,  no standardized documentation methods (or even requirements), etc.

Overall, I didn't see this is a problem. I expected my first job to embrace all of these ideas and to teach them to me on the job. Then I got my first job (full stack web development) at a big corporation and I realized that we do none of these things. In fact I, the least experienced on the team, am the one who is spearheading attempts to bring my team up to speed with "modern" programming techniques - as I worry that not doing so is professional suicide down the road.

First I began with logging software (log4J), but then I quickly moved on to writing my own styleguide, then abandoning it for the Google styleguide - and then I realized that our Java web development used hand-written front controllers, so I pushed for our adoption of Spring - but then I realized we had no unit tests, either, but I was already learning Spring... and as you can see, it becomes overwhelming all too quickly, especially when paired with normal development work. Furthermore, it is difficult for me to become "expert" enough in these methodologies to teach anyone else in them without devoting too much time to a single one of them, let alone them all.

Of all these techniques, which I see as "expected" in today's software development world, how do I integrate them into a team as a new player without overwhelming both myself and the team?

How can I influence my team to become more agile? is related, but I'm not an Agile developer like the asker here, and I'm looking at a much broader set of methodologies than Agile.

答:
A Direct Answer

Other answers make good 'meta-points' about adopting better practices but, just to give you some directly relevant guidance, here's a rough ordering of the best practices I'd suggest your team (or any team) adopt (first):

Source control

Issue tracking (project and task management)

Automated builds1

Automated deployments

1 A very much related practice is to automate, or at least document, setting-up the build and development environment of each app or software project you're developing or maintaining. It's much less useful tho because you're (hopefully) doing this infrequently or rarely.

Everything Else

You mention several other good practices – "unit testing, logging, database normalization, ... refactoring, ... documentation" – but these are all practices that can and should be adopted gradually and incrementally. None of them need to be adopted all at once and you'll probably better adopt them at all by adopting them carefully and mindfully.

The four practices I listed above will also make adopting, and experimenting with, new practices as easy as possible. For example, unit testing can be incorporated into your automated builds and documentation can be published as part of your automated deploys.

Some of the other practices you mention – "agile development, ... coding style guides, ... code reviews, ... standardized documentation methods" and frameworks (e.g. Spring) – are really optional or of dubious value. And that's true of a lot (most?) possible practices you'll discover or encounter.

Agile development isn't obviously superior to any other methodology used. And a lot of people (including myself) have had horrible experiences with it. But lots of people really like it (or love it) too. Try it!

Coding style guides can be helpful, especially for large projects, or in large teams, but it's also a lot of work to enforce those guidelines and that may not be the best use of the time of whomever is doing so.

Code reviews can be very helpful too – have you asked your coworkers to review your code? Keep in mind that you don't need a formal process to adopt good practices!

Documentation is great – do you have any at all? If so, good for you! Are you facing lots of extra work that could be prevented by having (more) "standardized" documentation? If you are, then that's probably something worth doing. However, say if your software is being used by a small group of people, you may not need any documentation. (Or you could directly incorporate the documentation into your software. That's always my preference.)

Frameworks are ... a (very sharp) double-edged sword. A nicely encapsulated and well-maintained solution for a non-core feature of your software is great ... until it isn't. I'm not sure what "hand-written front controllers" are exactly but there's no obvious explanation as to why they're inferior to code that leverages Spring. Have you considered encapsulating the common logic in all of these controllers into your own in-house framework? Adopting Spring, and rewriting all your existing code, could be an immense refactoring (or, more likely, rewriting) project and that might not be the best change you could make to your code. Of course you shouldn't write all of the software you use – frameworks (and libraries) are great! But maybe you don't have to use Spring (or an alternative) to write great (or good) web apps.


答:
It depends on what you intend to do with the content of the files.

If you ever need to make queries based on the content of the sheets (and I am pretty sure you will have to), I really think you should consider the table solution. I think there are some ways to improve your performance issues (batch insert...).


问:
What happens if some server side GPLv2 code is leaked?
So, I know that if you use GPLv2 code in some server side code, you do not need to release that code (as long as you're not distributing it, of course :). However, let's assume that you accidentally make a file from your server side codebase available... but it's a totally unintentional mistake.

Would you then need to release all of the code, if that is "distribution"?

Further, what if a malicious employee (I know, I know, but this is what law resolves!) puts a jar of some of your server code on the internet. You do what you can to take it down and take actions against that employee, but does that count as "distribution"?

答:
In the first case, for a bona fide accident, you are in all likelihood fine. If it's served up by accident, no one has any authorization to download the file in the first place, and so therefore it likely wouldn't be considered a distribution. If someone has a beef with the company though, it may take going to court to decide that, as this issue hasn't been tested in court to my knowledge.

In the case of the malicious employee, the employee has no authorization to propagate the work. The company will not be 'required' to distribute their software per the GPL from then on, as it wasn't really distributed according to the GPL in the first place.

Punishing the employee or cleaning up what to do after is a question for a law firm.


答:
If a rogue employee takes your source code and distributes it, then it is the rogue employee and not you who does the distributing. The rogue employee has to provide source code or is guilty of a GPL violation. However, since he doesn't have the right to distribute the source code (because that source code is yours), he can't distribute it and is guilty of that GPL violation. That's his problem, not yours. </p>

<p>(You may have a problem if the rogue employee is high enough in the company that he actually has authorisation to distribute the software. Say your VP for software development distributes the software, then the company is quite likely responsible for his actions. That would also depend on the country where this happens). </p>

Title: What happens if some server side GPLv2 code is leaked?

Body:
So, I know that if you use GPLv2 code in some server side code, you do not need to release that code (as long as you're not distributing it, of course :). However, let's assume that you accidentally make a file from your server side codebase available... but it's a totally unintentional mistake.

Would you then need to release all of the code, if that is "distribution"?

Further, what if a malicious employee (I know, I know, but this is what law resolves!) puts a jar of some of your server code on the internet. You do what you can to take it down and take actions against that employee, but does that count as "distribution"?

Body:
If a rogue employee takes your source code and distributes it, then it is the rogue employee and not you who does the distributing. The rogue employee has to provide source code or is guilty of a GPL violation. However, since he doesn't have the right to distribute the source code (because that source code is yours), he can't distribute it and is guilty of that GPL violation. That's his problem, not yours.

(You may have a problem if the rogue employee is high enough in the company that he actually has authorisation to distribute the software. Say your VP for software development distributes the software, then the company is quite likely responsible for his actions. That would also depend on the country where this happens).


问:
API authentication with a single ID
A typical API authentication usually rely on a pair of API ID + SECRET, my question is: if the API ID is unique and randomly generated and is considered strong enough (e.g. SHA512), why a SECRET is even needed?

What if, I created an API only need a API ID for authentication, what would be the drawback, especially in term of security?

Some people might say, it is easy to revoke the SECRET without changing API ID, but this does not sound since if you need to update the SECRET, you need to modify the config/source code as well.

Internally the API program can still have some unique ID to identify the client, but this information does not need to expose to the client code, just use a single ID is enough, right?

Actually I would considered using a single API ID is more secure - since when you change , it is more hard to identify the client (as there is no constant API ID)

Any conveats?

答:
This is a lot like asking why we have both a username and a password for all our regular internet accounts, when arguably just a password is sufficient.

The first reason is actually contained in your question:

Actually I would considered using a single API ID is more secure - since when you change , it is more hard to identify the client (as there is no constant API ID)

That's the problem. Many services simply don't work if they can't remember who you are. Imagine if an e-mail provider "lost" all e-mail you'd ever sent or received every time you changed your password. Nobody would ever use them.

The second reason is that it's not more secure. Either way, the attacker only needs to figure out the secret in order to impersonate you. The presence of a non-secret does not automatically make the secret any less secure (assuming the method used to generate the secret and non-secret is cryptographically secure).

Title: API authentication with a single ID


问:
Why store flags/enums in a database as strings instead of integers?
I've been browsing SQL dumps of some famous CMSes, including Drupal 7, Wordpress (some quite very old version), and some custom application based on Python.

All of these dumps contained data with string flags instead of integer ones. For example, a post's status was represented as published, closed, or inherit rather than 1, 2, or 3.

I have quite limited experience in design of databases and I have never went past simple SQLs, but I was always taught that I should use numeric/integer flags for data like this. It's obvious that tinyint consumes much less space in a database than, for example, varchar(9).

So what am I missing? Isn't this a waste of data storage and a data redundancy? Wouldn't browsing, searching and indexing be a bit faster if these columns used integers instead of strings?

答:
Yes, storing things such as yes or true will take more space than a tinyint. This should not be surprising. It also makes indexing and thus joins less efficient for the database. It also has the penalty of possible confusion for what is the correct value (yes vs y).

However, there are many approaches that look similar to storing strings in the database (in particular MySQL) that are efficient.

First, MySQL has an enum type (docs) which can look very much like a Boolean or restricted set of strings when set up that way. It also enforces only valid values are entered. This is often much more useful than storing 1, 2 or 3 as a value as the meaning is conveyed with the information.  The enum comes with the penalty that a schema change is required to add or remove types.

This brings us to a child table and foreign keys (applicable to all databases).  Yes, you are storing some value as a key (back to the 1, 2 or 3) and the value of published, closed, and inherit are stored in another table. Using a view (docs) it is then possible to make it look like the table contains the string rather than the key.  This has the advantage that no schema change is required to add or remove entries from the child table.

Exactly how things are stored would require one to look at the actual DDL of the schema to determine what method is used and get some hint of which trade offs they have selected.


问:
What is the difference between writing test cases for BDD and TDD?
I have been learning writing test cases for BDD (Behavior Driven Development) using specflow. If I write comprehensive tests with BDD, is it necessary to write TDD (Test Driven Development) test separately? Is it necessary to write test cases for both TDD and BDD separately, or are they effectively the same thing?

It seems to me that both are same, the only difference being that BDD test cases can be understood by non developers and testers.

答:
BDD adds one more level of abstraction to the tests. The higher level code (usually in txt) describes what the system tests, the lower level code describes how it tests it. So a BDD framework can use a TDD framework in the lower level code.

This helps a lot by staying DRY. By TDD you can easily end up with "wet" tests containing a lot of code duplication, which make them easy to break by refactoring the code and the tests with it. By BDD you have to modify only the lower abstraction level by refactoring the code, so if the specification does not change, the higher level code won't change.

Btw. this is simple Clean Code, usually it is enough to read the high abstraction level stuff to understand what it does, and dig deeper to the lower abstraction level testing code only if you really need it. This makes (test) code easier to understand in general.

A bad example (because it is too simple):

jasmine TDD style

calculator.add.specs

```<code>describe("Calculator: add", function (){

    it("should be able to add 2 numbers together", function (){
        var total = add(1, 2);
        expect(total).toBe(3);
    });

    it("should be able to add 3 numbers together", function (){
        var total = add(1, 2, 3);
        expect(total).toBe(6);
    });
});
</code>```

jasmine-cucumber BDD style

calculator.specs

```<code>feature('Calculator: add')
    .scenario('should be able to add 2 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .then('I should get "3"')
    .scenario('should be able to add 3 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .and('I add "3"')
        .then('I should get "6"')
</code>```

calculator.steps

```<code>featureSteps('Calculator:')
    .before(function(){
        this.values = [];
        this.total = null;
    })
    .when('I enter "(.*)"', function(value){
        this.values.push(Number(value));
    })
    .when('I add "(.*)"', function(value){
        this.values.push(Number(value));
    })
    .then('I should get "(.*)"', function(expectedTotal){
        this.total = add.apply(null, this.values);
        expect(this.total).toBe(Number(expectedTotal));
    });
</code>```

implementation

calculator.js

```<code>function add(){
    var args = Array.prototype.slice.call(arguments);
    var total = 0;
    for (var i in args)
        total += args[i];
    return total;
}
</code>```

Now if I rename the add() function to sum() I have to change the TDD code in 2 places, while the BDD code only in a single place in the steps file. Ofc. adding one more abstraction level requires more code...

Body:
BDD adds one more level of abstraction to the tests. The higher level code (usually in txt) describes what the system tests, the lower level code describes how it tests it. So a BDD framework can use a TDD framework in the lower level code.

This helps a lot by staying DRY. By TDD you can easily end up with "wet" tests containing a lot of code duplication, which make them easy to break by refactoring the code and the tests with it. By BDD you have to modify only the lower abstraction level by refactoring the code, so if the specification does not change, the higher level code won't change.

Btw. this is simple Clean Code, usually it is enough to read the high abstraction level stuff to understand what it does, and dig deeper to the lower abstraction level testing code only if you really need it. This makes (test) code easier to understand in general.

A bad example (because it is too simple):

jasmine TDD style

calculator.add.specs

describe("Calculator: add", function (){

    it("should be able to add 2 numbers together", function (){
        var total = add(1, 2);
        expect(total).toBe(3);
    });

    it("should be able to add 3 numbers together", function (){
        var total = add(1, 2, 3);
        expect(total).toBe(6);
    });
});

jasmine-cucumber BDD style

calculator.specs

feature('Calculator: add')
    .scenario('should be able to add 2 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .then('I should get "3"')
    .scenario('should be able to add 3 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .and('I add "3"')
        .then('I should get "6"')

calculator.steps

featureSteps('Calculator:')
    .before(function(){
        this.values = [];
        this.total = null;
    })
    .when('I enter "(.*)"', function(value){
        this.values.push(Number(value));
    })
    .when('I add "(.*)"', function(value){
        this.values.push(Number(value));
    })
    .then('I should get "(.*)"', function(expectedTotal){
        this.total = add.apply(null, this.values);
        expect(this.total).toBe(Number(expectedTotal));
    });

implementation

calculator.js

function add(){
    var args = Array.prototype.slice.call(arguments);
    var total = 0;
    for (var i in args)
        total += args[i];
    return total;
}

Now if I rename the add() function to sum() I have to change the TDD code in 2 places, while the BDD code only in a single place in the steps file. Ofc. adding one more abstraction level requires more code...


问:
Differences in design/thought process for OO in Java and JavaScript
Despite sharing a similar name and syntax, Java and JavaScript are quite different. However, they both have Object Oriented features.

As a JavaScript novice, the main differences that I can see between Java and JavaScript's Object Orientation is in inheritance and "class"/object description syntax.

Assuming the above is correct, would thinking about my JavaScript objects as Java objects while designing and subsequently "translating" them to JavaScript code be a good idea? My thinking is that both languages' respective objects boil down to properties and methods/functions. I don't plan to use inheritance or dynamically add properties/functions.

Would taking this approach lead to difficulties or miss major features of JavaScript?

答:
For the most part, you can write very Java-like code in JavaScript, but it's usually simpler not to.  There are two pretty major factors that affect your design:  dynamic typing and functional-style callbacks.

Dynamic typing means you don't use interfaces, and you don't need to create a lot of those little classes that do nothing else but implement interfaces or create glue between other classes or other things done to make static type systems happy.    People who have only programmed in Java previously often don't realize just how much of it is type system boilerplate.  Java is pretty bad in that department, even compared to other statically-typed languages.

Functional-style callbacks means instead of creating an object with an actionPerformed method, you just pass a function straight in.  This eliminates a lot of the classes you create for the sole purpose of receiving asynchronous events, and gives you a lot more flexibility in what data gets passed back to you.

What you'll find is that JavaScript data model objects tend to be fairly similar to their Java counterparts, but control and glue logic usually is very different.


答:
As I was clearing up the description, a potential third option (Redesigned java class) dawned on me. So I am going to investigate it further as it looks promising with no model impact.
Let me know if this is not a good option based on the use case and if you see any issues with it.</p>


问:
What's the correct commit message in a multi-project repository
Somewhere else there was a discussion on putting several projects in one large repository.  My question is, how does a good commit message look in those type of repos?

I usually prepend each commit message (via git hook) with a JIRA story ID [XYZ-123] and then add the information about the commit. However, having 10 or 20 projects in one repository, makes it difficult to know to which project is the commit referring. Adding a project name in the commit message might be a possibility, at the cost of reducing the comment space.

How have other programmers dealt with this?

答:
I don't think the projects in that question are the same as the ones in your case.

The project's in that question are build projects - they are all different components of the same application, divided into projects for the ease of building and releasing. Such projects, even when placed in different repositories, should share the same project in the ALM, because tickets rarely map cleanly to a single component:

When you open a feature request ticket, implementing it often requires modification of multiple components. Having to open tickets in all the different projects is not only cumbersome but also splits the design discussion into many comment sections and makes it hard to follow.

When you open a bug ticket, you can only guess what component the bug belongs to until you investigate - and you don't want to postpone the ticket opening until that investigation(which might be done by someone other than the ticket opener) is done. Also, while not as often as new features, some bugs do need fixing in multiple components.

In your case, since you find it reasonable to have a JIRA project for each project, I'm going to assume they are actual projects, each an application of it's own. If I'm right - you shouldn't put them all in the same repository! It has a very important benefit in the question you referred to - it allows to put in the same commits changes to multiple components that depend on each other. But in your case this is simply not relevant - there is no justification to have commit messages that look like:

```<code>- Add UTF-32 encoding support to SuperTextEditor
- Fix weird crash in AwesomeMusicPlayer
- Switch the default browsing algorithm in AmazingArchiver
</code>```

These are all different changes to different projects that belong to different commits, and there can be no reason ever for you to want to bundle them together in the same commit - these projects should be each in it's own repository.

Putting multiple projects in the same repository is SVN thinking. SVN is a horrible SCM with a terrible design that forces you to use some gruesome hacks or else you won't find the mental strength to resist the argue to leave your 10th floor office from the window instead of the door. Putting multiple projects in one repository is one such hack, used mainly because it's so hard to keep track of multiple SVN repositories. Git doesn't have that problem - so just use separate repositories for separate projects!

Body:
I don't think the projects in that question are the same as the ones in your case.

The project's in that question are build projects - they are all different components of the same application, divided into projects for the ease of building and releasing. Such projects, even when placed in different repositories, should share the same project in the ALM, because tickets rarely map cleanly to a single component:

When you open a feature request ticket, implementing it often requires modification of multiple components. Having to open tickets in all the different projects is not only cumbersome but also splits the design discussion into many comment sections and makes it hard to follow.

When you open a bug ticket, you can only guess what component the bug belongs to until you investigate - and you don't want to postpone the ticket opening until that investigation(which might be done by someone other than the ticket opener) is done. Also, while not as often as new features, some bugs do need fixing in multiple components.

In your case, since you find it reasonable to have a JIRA project for each project, I'm going to assume they are actual projects, each an application of it's own. If I'm right - you shouldn't put them all in the same repository! It has a very important benefit in the question you referred to - it allows to put in the same commits changes to multiple components that depend on each other. But in your case this is simply not relevant - there is no justification to have commit messages that look like:

- Add UTF-32 encoding support to SuperTextEditor
- Fix weird crash in AwesomeMusicPlayer
- Switch the default browsing algorithm in AmazingArchiver

These are all different changes to different projects that belong to different commits, and there can be no reason ever for you to want to bundle them together in the same commit - these projects should be each in it's own repository.

Putting multiple projects in the same repository is SVN thinking. SVN is a horrible SCM with a terrible design that forces you to use some gruesome hacks or else you won't find the mental strength to resist the argue to leave your 10th floor office from the window instead of the door. Putting multiple projects in one repository is one such hack, used mainly because it's so hard to keep track of multiple SVN repositories. Git doesn't have that problem - so just use separate repositories for separate projects!


问:
angularjs events for launching modals
I want to be able to launch modal windows from different parts of my angular application for viewing or editing content without changing states/url.

My current approach is to create a module for each modal and in the run() method, add a $rootScope.$on listener. I can then $emit from anywhere in the app and pass a callback function for when the modal has finished doing it's thing for the item that $emitted to update itself if necessary. I understand I could also use promises instead of callbacks.

I am not so much concerned with callbacks/promises but more the fact that I am using $scope and $rootScope to dispatch and listen for events. Is there a better way of doing this such as having some sort of central event dispatching service, or is this just re-inventing what already exists in $rootScope?

Can anyone provide examples of a good approach?

答:
I think the cleaner way is to emit events, you can do it using a service to abstract this behavior, this service will do 3 things:

$emit the event

add a $q.defer() on the $emit

return a defer.promise to the caller

That way is transparent for the caller but the listener of the event must resolve or reject the event with the corresponding result or reason

Update

Here is a working example, using an eventEmitter service, and a eventListener modules, but probably should be more modular this separation, otherwise you will end up with a single module which handles all the listener for the entire application

Title: angularjs events for launching modals


问:
Is Visitor Pattern valid in this scenario?
The goal of my task is to design a small system which can run scheduled recurring tasks. A recurring task is something like "send an email to administrator every hour from 8:00 am to 5:00 pm, Monday through Friday".

I have a base class called RecurringTask.

```<code>public abstract class RecurringTask{

    // I've already figured out this part
    public bool isOccuring(DateTime dateTime){
        // implementation
    }

    // run the task
    public abstract void Run(){

    }
}
</code>```

And I have several classes which are inherited from RecurringTask. One of them is called SendEmailTask.

```<code>public class SendEmailTask : RecurringTask{
    private Email email;

    public SendEmailTask(Email email){
        this.email = email;
    }

    public override void Run(){
        // need to send out email
    }
}
</code>```

And I have a EmailService which can helps me to send out an email.

The last class is RecurringTaskScheduler, it's responsible for loading tasks from cache or database and run the task.

```<code>public class RecurringTaskScheduler{

    public void RunTasks(){
        // Every minute, load all tasks from cache or database
        foreach(RecuringTask task : tasks){
            if(task.isOccuring(Datetime.UtcNow)){
                task.run();
            }
        }
    }
}
</code>```

Here is my problem: where should I put EmailService?

Option1: Inject EmailService into SendEmailTask

```<code>public class SendEmailTask : RecurringTask{
    private Email email;

    public EmailService EmailService{ get; set;}

    public SendEmailTask (Email email, EmailService emailService){
        this.email = email;
        this.EmailService = emailService;
    }

    public override void Run(){
        this.EmailService.send(this.email);
    }
}
</code>```

There are already some discussions on whether we should inject a service into an entity, and most people agree it's not a good practice. See this article.

Option2: If...Else in RecurringTaskScheduler

```<code>public class RecurringTaskScheduler{
    public EmailService EmailService{get;set;}

    public class RecurringTaskScheduler(EmailService emailService){
        this.EmailService = emailService;
    }

    public void RunTasks(){
        // load all tasks from cache or database
        foreach(RecuringTask task : tasks){
            if(task.isOccuring(Datetime.UtcNow)){
                if(task is SendEmailTask){
                    EmailService.send(task.email); // also need to make email public in SendEmailTask
                }
            }
        }
    }
}
</code>```

I've been told If...Else and cast like above is not OO, and will bring more problems.

Option3: Change the signature of Run and create ServiceBundle.

```<code>public class ServiceBundle{
    public EmailService EmailService{get;set}
    public CleanDiskService CleanDiskService{get;set;}
    // and other services for other recurring tasks

}
</code>```

Inject this class into RecurringTaskScheduler

```<code>public class RecurringTaskScheduler{
    public ServiceBundle ServiceBundle{get;set;}

    public class RecurringTaskScheduler(ServiceBundle serviceBundle){
        this.ServiceBundle = ServiceBundle;
    }

    public void RunTasks(){
        // load all tasks from cache or database
        foreach(RecuringTask task : tasks){
            if(task.isOccuring(Datetime.UtcNow)){
                task.run(serviceBundle);
            }
        }
    }
}
</code>```

The Run method of SendEmailTask would be

```<code>public void Run(ServiceBundle serviceBundle){
    serviceBundle.EmailService.send(this.email);
}
</code>```

I don't see any big problems with this approach.

Option4: Visitor pattern.

The basic idea is create a visitor which will encapsulate services just like ServiceBundle.

```<code>public class RunTaskVisitor : RecurringTaskVisitor{
    public EmailService EmailService{get;set;}
    public CleanDiskService CleanDiskService{get;set;}

    public void Visit(SendEmailTask task){
        EmailService.send(task.email);
    }

    public void Visit(ClearDiskTask task){
        //
    }
}
</code>```

And we also need to change the signature of Run method. The Run method of SendEmailTask is

```<code>public void Run(RecurringTaskVisitor visitor){
    visitor.visit(this);
}
</code>```

It is a typical implementation of Visitor Pattern, and the visitor will be injected into RecurringTaskScheduler.

In summary:
Among these four approaches, which one is the best for my scenario? And are there any big difference between Option3 and Option4 for this problem?

Or do you have better idea on this problem? Thanks!

Update 5/22/2015: I think Andy's answer summarizes my intention really well; if you are still confused about the problem itself, I suggest reading his post first.

I just found out my problem is very similar to Message Dispatch problem, which leads to Option5.

Option5: Convert my problem to Message Dispatch.

There is a one-to-one mapping between my problem and Message Dispatch problem:

Message Dispatcher : Receive IMessage and dispatch sub classes of IMessage to their corresponding handlers. → RecurringTaskScheduler

IMessage : An interface or an abstract class. → RecurringTask

MessageA : Extends from IMessage, having some additional information. → SendEmailTask

MessageB : Another subclass of IMessage. → CleanDiskTask

MessageAHandler : When receive MessageA, handle it → SendEmailTaskHandler, which contains EmailService, and will send out an email when it receives SendEmailTask

MessageBHandler : Same as MessageAHandler, but handle MessageB instead. → CleanDiskTaskHandler

The hardest part is how to dispatch different kind of IMessage to different handlers. Here is a useful link.

I really like this approach, it doesn't pollute my entity with service, and it doesn't have any God class.

答:
Have you had a look at existing libraries e.g. spring quartz or spring batch (I'm not sure what fits your needs most)?

To your question:

I assume the problem is, that you want to persist some metadata to the task in a polymorphic way, so an e-mail task has e-mail addresses assigned, a log-task a log-level, and so on.
You can store a list of those in memory or in your database but to seperate concerns you don't want to have the entity polluted with service-code.

My proposed solution:

I would separate the running- and the data-part of the task, to have e.g. TaskDefinition and a TaskRunner. The TaskDefinition has a reference to a TaskRunner or a factory that creates one (e.g. if some setup is required like the smtp-host). The factory is a specific one - it only can handle EMailTaskDefinitions and returns only instances of EMailTaskRunners. This way it is more OO and change safe - if you introduce a new task-type you have to introduce a new specific factory (or reuse one), if you don't you can't compile.

This way you would end up with a dependency: entity layer --> service layer and back again, because the Runner needs information stored in the entity and probably wants to make an update to its state in the DB.

You could break the circle by using a generic factory, which takes a TaskDefinition and returns a specific TaskRunner, but that would require lots of ifs. You could use reflection to find a runner that is similarly named as your definition, but be cautious this approach can cost some performance, and may lead to runtime errors.

P.S. I'm assuming Java here. I think it's similar in .net. The main problem here is the double binding.

To the visitor pattern

I think it was rather intended to be used to exchange an algorithm for different kinds of data objects at runtime, than for pure double binding purposes. For example if you have different kinds of insurances and different kinds of calculating them, e.g. because different countries require it. Then you choose a specific calculation method and apply it on several insurances.

In your case you would choose a specific task-strategy (e.g. email) and apply it to all of your tasks, which is wrong because not all of them are email tasks.

P.S. I didn't test it, but I think your Option 4 won't work either, because it is double-binding again.


问:
Making use of constant data
My team is working on an android app. A co-worker and I have different ideas on how to load constant data.

To clarify, the data we are going to use

are 100 × (n × 〈integer-integer pair〉) where 10 < n < 20; not so many,

<s>are rarely going to be edited in the future</s>,

are supposed to be literally constant unless any single value is wrong,

are that the end users never need a direct acceess/modification to.

She suggested we put them in an XML, load & parse it during runtime in the name of "maintenance".

The data is actually light so XML parsing is not a big deal. However, doing unnecessary runtime tasks only to not mess up the code doesn't make sense to me. I'd rather write a simple program to read the raw data and spit out code to paste in.

input:

```<code>0   253
1   5150
2   6666
1   8126
3   11949
…
</code>```

output:

```<code>arrays.add(new Pair(0, 253));
arrays.add(new Pair(1, 5150));
arrays.add(new Pair(2, 6666));
arrays.add(new Pair(1, 8126));
arrays.add(new Pair(3, 11949));
…
</code>```

She is more experienced than me by a decade so I might be ignorant.

Can her approach ever be a good practice even though the data is not accessible from the user?

答:
doing unnecessary runtime tasks only to not mess up the code doesn't make sense to me

Actually, messing up the code just because to avoid some runtime tasks for which the running time does not matter does make much less sense to me. Your priorities should be

make it right

make it clean

make it fast enough

exactly in that order. See also: Is premature optimization really the root of all evil?

Title: Making use of constant data


问:
Call method in a disposable object at the beginning of a "using" statement
When we use the lock statement, it is essentially doing a Monitor.Enter at the beginning of the locking block and a Monitor.Exit at the end of the block. This process is automatically handled by the runtime.

A similar behaviour is at the end of the using block, it calls the Dispose method of IDisposable.

My question is, that if there is a way to call a method in the disposable object automatically at the beginning of the using block.

The reason I want to do this is that, I have implemented a custom ObservableCollection<T> that has 2 extra methods: BeginUpdate and EndUpdate. They are used to signal a batch update process. The collection won't raise the collection changed event until EndUpdate is called.

Although it's perfectly fine to call the 2 methods manually at the beginning and end of the batch process, but it'd be really nice if I can do something like this:

```<code>using(myCollection)
  foreach(var item in anotherBigList)
    myCollection.Add(item);
</code>```

答:
First I don't like using IDisposable on actual collection. It muddles the actual meaning of Disposable.

I would do it like this:

```<code>public class CollectionUpdateContext<T>: IDisposable // can also be inner class of custom collection
{
    public CollectionUpdateContext(ObservableCollection<T> inner)
    {
        inner.BeginUpdate();
    }

    public Dispose()
    {
        inner.EndUpdate();
    }
}

public class CustomCollection<T> : ObservableCollection<T>
{
    // whatever code of custom collection

    CollectionUpdateContext<T> Updating() // this can be also as extension method
    {
        return new CollectionUpdateContext<T>(this);
    }
}

using(myCollection.Updating())
  foreach(var item in anotherBigList)
    myCollection.Add(item);
</code>```

This way, it is clear that the using block is related to update mechanics of your collection. Also, because the IDisposable is not in custom collection, it forces programmer to call the Updating method. And lastly, it doesn't muddle the custom collection by adding IDisposable, that has different meaning.

Body:
First I don't like using IDisposable on actual collection. It muddles the actual meaning of Disposable.

I would do it like this:

public class CollectionUpdateContext<T>: IDisposable // can also be inner class of custom collection
{
    public CollectionUpdateContext(ObservableCollection<T> inner)
    {
        inner.BeginUpdate();
    }

    public Dispose()
    {
        inner.EndUpdate();
    }
}

public class CustomCollection<T> : ObservableCollection<T>
{
    // whatever code of custom collection

    CollectionUpdateContext<T> Updating() // this can be also as extension method
    {
        return new CollectionUpdateContext<T>(this);
    }
}

using(myCollection.Updating())
  foreach(var item in anotherBigList)
    myCollection.Add(item);

This way, it is clear that the using block is related to update mechanics of your collection. Also, because the IDisposable is not in custom collection, it forces programmer to call the Updating method. And lastly, it doesn't muddle the custom collection by adding IDisposable, that has different meaning.


答:
I completely disagree with that article. Services (concretely their "API") are important party of the Business Domain and as such will exist within Domain Model. And there is no problem with entities in business domain referencing something else in same business domain.

When X send mail to Y.

Is a business rule. And to do that, service that sends mail is needed. And entity that handles When X should know about this service.

But there are some problems with implementation. It should be transparent to user of the entity, that the entity is using a service. So adding the service in constructor is not a good thing. This is also an issue, when you are deserializing the entity from database, because you need to set both the data of the entity and instances of services. Best solution I can think of is to use property injection after the entity was created. Maybe forcing each newly created instance of any entity to go through "initialize" method that injects all entities the entity needs.

Title: Is Visitor Pattern valid in this scenario?

Body:
The goal of my task is to design a small system which can run scheduled recurring tasks. A recurring task is something like "send an email to administrator every hour from 8:00 am to 5:00 pm, Monday through Friday".

I have a base class called RecurringTask.

```<code>public abstract class RecurringTask{

    // I've already figured out this part
    public bool isOccuring(DateTime dateTime){
        // implementation
    }

    // run the task
    public abstract void Run(){

    }
}
</code>```

And I have several classes which are inherited from RecurringTask. One of them is called SendEmailTask.

```<code>public class SendEmailTask : RecurringTask{
    private Email email;

    public SendEmailTask(Email email){
        this.email = email;
    }

    public override void Run(){
        // need to send out email
    }
}
</code>```

And I have a EmailService which can helps me to send out an email.

The last class is RecurringTaskScheduler, it's responsible for loading tasks from cache or database and run the task.

```<code>public class RecurringTaskScheduler{

    public void RunTasks(){
        // Every minute, load all tasks from cache or database
        foreach(RecuringTask task : tasks){
            if(task.isOccuring(Datetime.UtcNow)){
                task.run();
            }
        }
    }
}
</code>```

Here is my problem: where should I put EmailService?

Option1: Inject EmailService into SendEmailTask

```<code>public class SendEmailTask : RecurringTask{
    private Email email;

    public EmailService EmailService{ get; set;}

    public SendEmailTask (Email email, EmailService emailService){
        this.email = email;
        this.EmailService = emailService;
    }

    public override void Run(){
        this.EmailService.send(this.email);
    }
}
</code>```

There are already some discussions on whether we should inject a service into an entity, and most people agree it's not a good practice. See this article.

Option2: If...Else in RecurringTaskScheduler

```<code>public class RecurringTaskScheduler{
    public EmailService EmailService{get;set;}

    public class RecurringTaskScheduler(EmailService emailService){
        this.EmailService = emailService;
    }

    public void RunTasks(){
        // load all tasks from cache or database
        foreach(RecuringTask task : tasks){
            if(task.isOccuring(Datetime.UtcNow)){
                if(task is SendEmailTask){
                    EmailService.send(task.email); // also need to make email public in SendEmailTask
                }
            }
        }
    }
}
</code>```

I've been told If...Else and cast like above is not OO, and will bring more problems.

Option3: Change the signature of Run and create ServiceBundle.

```<code>public class ServiceBundle{
    public EmailService EmailService{get;set}
    public CleanDiskService CleanDiskService{get;set;}
    // and other services for other recurring tasks

}
</code>```

Inject this class into RecurringTaskScheduler

```<code>public class RecurringTaskScheduler{
    public ServiceBundle ServiceBundle{get;set;}

    public class RecurringTaskScheduler(ServiceBundle serviceBundle){
        this.ServiceBundle = ServiceBundle;
    }

    public void RunTasks(){
        // load all tasks from cache or database
        foreach(RecuringTask task : tasks){
            if(task.isOccuring(Datetime.UtcNow)){
                task.run(serviceBundle);
            }
        }
    }
}
</code>```

The Run method of SendEmailTask would be

```<code>public void Run(ServiceBundle serviceBundle){
    serviceBundle.EmailService.send(this.email);
}
</code>```

I don't see any big problems with this approach.

Option4: Visitor pattern.

The basic idea is create a visitor which will encapsulate services just like ServiceBundle.

```<code>public class RunTaskVisitor : RecurringTaskVisitor{
    public EmailService EmailService{get;set;}
    public CleanDiskService CleanDiskService{get;set;}

    public void Visit(SendEmailTask task){
        EmailService.send(task.email);
    }

    public void Visit(ClearDiskTask task){
        //
    }
}
</code>```

And we also need to change the signature of Run method. The Run method of SendEmailTask is

```<code>public void Run(RecurringTaskVisitor visitor){
    visitor.visit(this);
}
</code>```

It is a typical implementation of Visitor Pattern, and the visitor will be injected into RecurringTaskScheduler.

In summary:
Among these four approaches, which one is the best for my scenario? And are there any big difference between Option3 and Option4 for this problem?

Or do you have better idea on this problem? Thanks!

Update 5/22/2015: I think Andy's answer summarizes my intention really well; if you are still confused about the problem itself, I suggest reading his post first.

I just found out my problem is very similar to Message Dispatch problem, which leads to Option5.

Option5: Convert my problem to Message Dispatch.

There is a one-to-one mapping between my problem and Message Dispatch problem:

Message Dispatcher : Receive IMessage and dispatch sub classes of IMessage to their corresponding handlers. → RecurringTaskScheduler

IMessage : An interface or an abstract class. → RecurringTask

MessageA : Extends from IMessage, having some additional information. → SendEmailTask

MessageB : Another subclass of IMessage. → CleanDiskTask

MessageAHandler : When receive MessageA, handle it → SendEmailTaskHandler, which contains EmailService, and will send out an email when it receives SendEmailTask

MessageBHandler : Same as MessageAHandler, but handle MessageB instead. → CleanDiskTaskHandler

The hardest part is how to dispatch different kind of IMessage to different handlers. Here is a useful link.

I really like this approach, it doesn't pollute my entity with service, and it doesn't have any God class.


答:
A virtual destructor adds a runtime cost. The cost is especially great if the class does not have any other virtual methods. The virtual destructor is also only needed in one specific scenario, where an object is deleted or otherwise destroyed through a pointer to a base class. In this case, the base class destructor must be virtual, and the destructor of any derived class will be implicitly virtual. There are a few scenarios where a polymorphic base class is used in such a way that the destructor does not need to be virtual:

If instances of derived classes are not allocated on the heap, e.g. only directly on the stack or inside other objects. (Except if you use uninitialized memory and placement operator new.)

If instances of derived classes are allocated on the heap, but deletion happens only through pointers to the most derived class, e.g. there is a std::unique_ptr<Derived>, and the polymorphism happens only through non-owning pointers and references. Another example is when objects are allocated using std::make_shared<Derived>(). It is fine to use std::shared_ptr<Base> as well as long as the initial pointer was a std::shared_ptr<Derived>. This is because shared pointers have their own dynamic dispatch for destructors (the deleter) that does not necessarily rely on a virtual base class destructor.

Of course, any convention to use objects only in the aforementioned ways can easily be broken. Therefore, Herb Sutter's advice remains as valid as ever: "Base class destructors should either be public and virtual, or protected and non-virtual." That way, if someone attempts to delete a pointer to a base class with non-virtual destructor, (s)he will most likely receive an access violation error at compile time.

Then again there are classes that are not designed to be (public) base classes. My personal recommendation is to make them final in C++11 or higher. If it's designed to be a square peg, then chances are it will not work very well as a round peg. This is related to my preference for having an explicit inheritance contract between base class and derived class, for the NVI (non-virtual interface) design pattern, for abstract rather than concrete base classes, and my abhorrence of protected member variables, among other things, but I know all of these views are controversial to some degree.

Title: When NOT to use virtual destructors?


问:
How to determine if set of ordered coordinates form a simple curve?
I hope it is the right place to ask this. I wasn't sure if it belongs to Stack Overflow or Computer Science.

Eventually this seemed more suitable.

Anyway, some background first:

A closed curve, is a curve with no endpoints and which completely encloses an area.

A simple curve, is a curve that does not cross itself.

Example:

Now, given n ordered (x,y) coordinates that represents mouse movement, it is easy to determine if they form a closed curve (given an upper bound on the allowed distance between two points, of-course), but is there an algorithm that will determine whether or not the coordinates form a simple curve?

I tried to look online for an answer, but couldn't find relevant solutions.

答:
You can check each point pair P[i],P[i+1] against each point pair P[j],P[j+1]

If any of the lines segments they create intersect then the curve is not simple.

Naively check each line:

```<code>for(int i = 0; i < n-3; i++)
    for(int j = i+2; j < n-1; j++)
        if(doIntersect(new Line(P[i],P[i+1]), new Line(P[j],P[j+1]));
</code>```

I skip checking P[i],P[i+1] against P[i+1],P[i+2] because they always intersect on the endpoint P[i+1]

This algorithm can be sped up by sorting the list of segments by left most x and then only check lines that have an endpoint left of the rightmost x of the current segment.

Body:
You can check each point pair P[i],P[i+1] against each point pair P[j],P[j+1]

If any of the lines segments they create intersect then the curve is not simple.

Naively check each line:

for(int i = 0; i < n-3; i++)
    for(int j = i+2; j < n-1; j++)
        if(doIntersect(new Line(P[i],P[i+1]), new Line(P[j],P[j+1]));

I skip checking P[i],P[i+1] against P[i+1],P[i+2] because they always intersect on the endpoint P[i+1]

This algorithm can be sped up by sorting the list of segments by left most x and then only check lines that have an endpoint left of the rightmost x of the current segment.