答:
This type of situation pops up quite often.  For example, files can only be manipulated while open, and if you try to do something with a file after it has been closed, you get a runtime exception.

Your desire (expressed in your previous question) to use the type system of the language so as to ensure that the wrong thing cannot even happen is noble, since compile-time errors are always preferable over runtime errors.  However, there is no design pattern that I know of for this type of situation, probably because it would end up causing more problems than it would solve.  (It would be impractical.)

The closest thing to your situation that I know of is to model different states of an object which correspond to different capabilities via extra interfaces, but this way you are only reducing the number of places in the code where a runtime error may occur, you are not eradicating the possibility of a runtime error.

So, in your situation, you would declare a number of interfaces describing what can be done with your object in its various states, and your object would return a reference to the right interface upon a state transition.

So, for example, the approve() method of your class would return an ApprovedApplication interface.  The interface would be implemented privately, (via a nested class,) so code which only has a reference to an Application cannot invoke any of the ApprovedApplication methods.  Then, code which manipulates an approved application explicitly states its intention to do so at compilation time by requiring an ApprovedApplication to work with. But of course, if you store this interface somewhere, and then you proceed to use this interface after the decline() method has been invoked, you will still get a runtime error.  I do not think there is a perfect solution to your problem.

Title: Design pattern for "operation on object allowed, only if object is in certain state"

Body:
For example:

Only job applications that are not yet in review or approved, can be updated. In other words, a person can update his job appliance form until HR starts reviewing it, or it's already acepted.

So a job application can be in 4 states:

APPLIED(initial state), IN_REVIEW, APPROVED, DECLINED

How do I achieve such behavior?

Surely I can write an update() method in Application class, check
  Application state, and do nothing or throw exception if Application is
  not in required state

But this kind of code does not make it obvious such a rule exists, it allows anyone to call update() method, and only after failing a client knows such operation was not permitted. Therefore client needs to be aware that such an attempt might fail, therefore take caution. Client being aware of such things also means that logic is leaking outside.

I tried creating different classes for each state (ApprovedApplication etc.) and put allowed operations on only allowed classes, but this kind of approach feels wrong too.

Is there an official design pattern, or a simple piece of code, to implement such behavior?


问:
Design pattern for "operation on object allowed, only if object is in certain state"
For example:

Only job applications that are not yet in review or approved, can be updated. In other words, a person can update his job appliance form until HR starts reviewing it, or it's already acepted.

So a job application can be in 4 states:

APPLIED(initial state), IN_REVIEW, APPROVED, DECLINED

How do I achieve such behavior?

Surely I can write an update() method in Application class, check
  Application state, and do nothing or throw exception if Application is
  not in required state

But this kind of code does not make it obvious such a rule exists, it allows anyone to call update() method, and only after failing a client knows such operation was not permitted. Therefore client needs to be aware that such an attempt might fail, therefore take caution. Client being aware of such things also means that logic is leaking outside.

I tried creating different classes for each state (ApprovedApplication etc.) and put allowed operations on only allowed classes, but this kind of approach feels wrong too.

Is there an official design pattern, or a simple piece of code, to implement such behavior?

答:
Application could be an interface, and you could have an implementation for each of the states. The interface could have a moveToNextState() method, and this would hide all the workflow logic.

For the client's needs, there could be also a method returning directly what you can do and not (i.e. a set of booleans), instead of just the state, so that you don't need a "checklist" in the client (I assume the client to be an MVC controller or UI anyway).

However, instead of throwing an exception you could just do nothing and log the attempt. This is safe at runtime, rules were enforced and the client had ways to hide the "update" controls.

ContentLicense: CC BY-SA 3.0


问:
Drawbacks of a master error handler?
I'm thinking that I could simplify my life by making an exception handling class that I can just ship all exceptions to and it will handle appropriately.

Ideally:

```<code>def dostuff():
  try:
    dothis()
  except Exception e:
    Handler.handle(e)
</code>```

To avoid

```<code>def dostuff():
  try:
    dothis()
  except ValueError e:
    #handle ValueError
  except IndexError e:
    #handle IndexError
</code>```

The Handler class would have all the logic to handle exception appropriately and you could pass some arguments to specify how to handle the error, but there would be reasonable defaults to make thing easy.

This seems like either a great idea or a terrible one. Its possible that I will find it lacks the usefulness I'm looking for. But I feel like there may be some serious drawbacks that I'm not seeing. I don't think I've seen this approach often. Is there a reason?

I'm working in Python right now, but I think its not really a language specific question.

答:
A master error handler is akin to a god class, an anti pattern in modular design.

On the other hand, there is a design pattern called Error Handler which allows you to centralize control of errors that are the same.

Title: Drawbacks of a master error handler?


问:
Single Source Shortest Path
In the lecture we are taught that we can solve All Pairs Shortest Path(APSP) with matrix multiplication.

In APSP we are creating a distance table for all the distances between each nodes in the graph. And now the question is "Is it possible to solve Single Source Shortest Path(SSSP) problem with matrix multiplication? If it is, then how?"

If you give me an explanation how to accomplish this I would appreciate.

答:
Single Source Shortest Path?

Since all pair shortest path is possible with Matrix Multiplication and single source is a subset for all pair source, Single source shortest path is also possible. Just ignore the other pairs.

Matrix-Multiplication Based Algorithm

Consider the multiplication of the weighted adjacency matrix with itself - except, in this case, we replace the multiplication operation in matrix multiplication by addition, and the addition operation by minimization

Notice that the product of weighted adjacency matrix with itself returns a matrix that contains shortest paths of length 2 between any pair of nodes

It follows from this argument that An contains all shortest paths

An is computed by doubling powers - i.e., as A, A2, A4, A8, ...

We need log(n) matrix multiplications, each taking time O(n3)

The serial complexity of this procedure is O(n3 log (n))

This algorithm is not optimal, since the best known algorithms have complexity O(n3)

Title: Single Source Shortest Path


问:
Many asynchronous calls vs single call to the API
We are developing a REST API which among others is going to be consumed by an HTML5 frontend via javascript. The application is for use within the organization and usually has about 300 users, but we want to scale well up to 1000 users or so.

Normally connections to the API will be made within the LAN so the quality and latency of the connection will be good, although it is not excluded occasional use over the Internet where connections could be slower and with more lag via 3G/4G.

The two options that we thought are:

The frontend will make several simultaneous asynchronous calls to the API to load the various components of the interface.

Pros: Simplicity.

Cons: More connections to the server.

The controller of the frontend will make a single call to the API passing as parameters which objects need to be fetched.

Pros: Only one connection to the server, although the server will make several connection to the database.

Cons: Requires mechanisms in both frontend and API. It complicates the design.

Further explanations:
There will be different resources .../Product .../Locations etc. These resources could be fetched alone, but there will be another abstract resource
.../screen?Product&Locations
that will fetch both in one call.

答:
Option 1 (multiple async calls) is the best choice because:

each individual call is its own entity, so you can retry individually if something happens to fail. In the monolithic 'one-call' architecture, if one thing fails you have to do the entire call again

the server side code will be simpler: again, modularity, meaning that different developers can work on different API resources

In a typical MVC pattern it doesn't make sense to have one API call load multiple separate resources; for example, if you make a request to /products to get a list of products to show on a page, and you also want to display a list of locations where popular products are sold, you have two separate resources: Product and Location. Though they are displayed on the same page, you can't logically make a call to /products and have it also return locations as well

your logging/utilization reports will be simpler in the modular approach. If you make a request to /products and you're also loading locations, your log files are going to be really confusing

if you have a problem with a particular resource, the one-call approach will cause the entire page to break and it won't be obvious to your users what broke - and this means it will take longer for your team to fix the issue; however, in the modular approach if one thing breaks, it will be very obvious what broke and you can fix it faster. It also won't ruin the rest of the page (unless things are too closely coupled...)

it will be easier to make changes in general if things are separated; if you have 5 resources being loaded by one API call, it will be harder to figure out how to not break things when you want to change something

The whole point is that resources are separate, and in a REST API returning many separate resources from a single API path doesn't make sense, even if you're "saving connections to the server". By the way, using parameters to conditionally load (different) resources is not RESTful.

All that said, the only logical option is to make multiple async requests to separate resources: take the modular approach!

PS - Don't prematurely optimize away "connections to the server", especially when HTTP connections are incredibly low overhead and you're on a LAN. That kind of thinking instead of choosing the simpler design right off the bat is going to get you into trouble later.


问:
When is Efferent / Afferent coupling good or bad
I have a software patterns exam this week and one of the topics we are to study is Efferent and Afferent coupling.

I understand a package has a high Ce (efferent coupling) if it depends on a number of other types.

For example:

```<code>class Car{
    Engine engine;
    Wheel wheel;
    Body body;
}
</code>```

This class would have a high efferent coupling because it depends on the Engine, Wheel and Body types.

Whereas the type "Wheel" would have a high Ca (afferent coupling) if several other packages depended on it (Car, Plane, Bicycle).

One of the possible questions on our exam is, when is Efferent / Afferent coupling good or bad? This seems odd to me because logically a program would need packages / classes with both high Efferent / Afferent coupling.

Does anybody have an example of when / where high efferent or afferent coupling is good / bad??

Thanks !

答:
Afferent

If something uses a bunch of different stuff (high number of afferent couplings), then it could be prone to break if any of those things change.

Instability = 1

Efferent

If something is used by a bunch of different stuff (high number of efferent couplings), then it could be prone to break a lot of things if it changes.

Instability = 0

Stability

Martin's definition of "stability" is an exotic blend between "difficult to change" and "having few reasons to change". Yet his instability metric only describes "difficulty of change". "Reasons to change" will have a lot more to do with factors that can't be easily calculated, like just designing your interfaces appropriately, at an appropriate level of abstraction, and understanding user-end requirements more clearly upfront.

So high efferent coupling with low afferent coupling yields stability (as in something difficult to change since it'll break a bunch of stuff), the opposite yields instability (as in something easy to change since it won't break a bunch of stuff).

A large number of afferent couplings could be an indicator that your design lacks focus -- it's using a whole bunch of different stuff so maybe it lacks a clear, singular responsibility.

A large number of efferent couplings could initially be interpreted as a really good thing, as it indicates that your design is being widely (re)used. Yet that would be bad if you feel tempted to change the design often in ways that breaks everything. So with a large number of efferent couplings comes the need for such packages to have "few or no reasons to change". The designs should be stable in the ideal sense of not having reasons to change, since they will likewise be very difficult to change.

Stable Abstractions Principle

Concepts like dependency inversion (which naturally calls for dependency injection) and SAP (stable abstractions principle) all suggest that dependencies flow towards abstractions. And there's a simple reason why when considering the "stability" in the context of having "few reasons to change". An abstract interface mentions no concrete details, it only focuses on "what to do" instead of "what things are", and thus has fewer reasons to change. The accelerated graphics port on our motherboards (abstract interface) has fewer reasons to undergo a design change than the GPU that plugs into it (a concrete detail).

Reusability vs. Reuse

A personal kind of metric of my own if I can suggest one which somewhat collides with Martin's is this notion I like to push that the most reusable libraries should seek to minimally reuse other code. That pushes instability towards a hard 0. It's for the practical reasons of having minimum reasons to change, but also to promote the easiest library to deploy. A general-purpose, widely-used library that depends on a dozen different libraries has a lot of reasons to change, as well as an awkwardly-bundled distribution which can be difficult to deploy. The difference here is that "reasons to change" in my case extends even to implementation, as it's coming from a library-oriented view that seeks to release stable versions of the library. Martin might discount the implementation as a very separate part, and only consider the metrics associated with the library's interface (which could be a whole lot more stable than its implementation).

From a distribution point of view, implementation and interface blur together to yield user dependencies to a stable or unstable library. From an interface point of view, only the interface is used and the implementation details associated are completely separate.


答:
I'm nodding my head on different bits of the various answers but the OP seems to still have the concern of flow control. There is too much to try to coalesce in words. I'm just going to right some code - The State Pattern.

State Names as Past Tense

"In_Review" is not a state perhaps but a transition, or process. Otherwise your state names should be consistent: "Applying", "Approving", "Declining", etc. OR have "Reviewed" too. Or not.

The Applied state does a review transition and sets state to Reviewed. Reviewed state does an approval transition and sets state to Approved (or Declined).

```<code>// Application class encapsulates state transition,
// the client is unable to directly set state.
public class Application {
    State currentState = null;

    State AppliedState    = new Applied(this);
    State DeclinedState   = new Declined(this);
    State ApprovedState   = new Approved(this);
    State ReviewedState   = new Reviewed(this);

    public class Application (ApplicationDocument myApplication) {
        if(myApplication != null && isComplete()) {
            currentState = AppliedState;
        } else {
            throw new ArgumentNullException ("Your application is incomplete");
            // some kind of error communication would probably be better
        }
    }

    public apply()    { currentState.apply(); }
    public review()   { currentState.review(); }
    public approve()  { currentState.approve(); }
    public decline()  { currentState.decline(); }

    //These could be done via an enum. I like enums!
    protected void setSubmittingState() {}
    protected void setApproveState() {}
    // etc. ...
}

// could be an interface if we don't have any default or base behavior.
public abstract class State {
    protected Application theApp;
    // maybe these return an object communicating errors / error state.
    public abstract void apply();
    public abstract void review();
    public abstract void accept();
    public abstract void decline();
}

public class Applied implements State {
    public Applied (Application newApp) {
        if(newApp != null)
            theApp = newApp;
        else
            throw new ArgumentNullException ("null application argument");
     }

    public override void apply() {
        // whatever is appropriate when already in "applied" state
        // do not do any work on behalf of other states!
        // throwing exceptions here is not appropriate, as others
        // have said.
      }

    public override void review() {
        if(recursiveBureaucracyBuckPassing())
            theApp.setReviewedState();
    }

    public override void decline() { // ditto  }
}

public class Reviewed implements State {}
public class Approved implements State {}
public class Declined implements State {}
</code>```

Edit - Error Handling Comments

A recent comment:

...  if you are attempting to loan a book which is already issued to somebody else the Book model will contain the logic to prevent it's state from changing. This might be via a return value (e.g. a boolean successful yay/nay, or status code) or an exception (e.g. IllegalStateChangeException) or some other means. Irrespective of the means chosen, this aspect is not covered as part of this (or any) answer.

And from the original question:

But this kind of code does not make it obvious such a rule exists, it allows anyone to call update() method, and only after failing a client knows such operation was not permitted.

There is more design work to do. There is no Unified Field Theory Pattern. The confusion comes from assuming the state transition framework will do general application functions and error handling. That feels wrong because it is. The answer shown is designed for controlling state change.

Surely I can write an update() method in Application class, check Application state, and do nothing or throw exception if Application is not in required state

This suggests there are three functionalities working here: The State, Updating, and interaction of the two. In this case Application is not the code I've written. It may use it to determine current state. Application is not the applicationPaperwork either. Application is not the interaction of the two, but could be a general StateContextEvaluator class. Now Application will orchestrate these component interactions and then act accordingly, like emitting an error message.

End Edit

Body:
I'm nodding my head on different bits of the various answers but the OP seems to still have the concern of flow control. There is too much to try to coalesce in words. I'm just going to right some code - The State Pattern.

State Names as Past Tense

"In_Review" is not a state perhaps but a transition, or process. Otherwise your state names should be consistent: "Applying", "Approving", "Declining", etc. OR have "Reviewed" too. Or not.

The Applied state does a review transition and sets state to Reviewed. Reviewed state does an approval transition and sets state to Approved (or Declined).

// Application class encapsulates state transition,
// the client is unable to directly set state.
public class Application {
    State currentState = null;

    State AppliedState    = new Applied(this);
    State DeclinedState   = new Declined(this);
    State ApprovedState   = new Approved(this);
    State ReviewedState   = new Reviewed(this);

    public class Application (ApplicationDocument myApplication) {
        if(myApplication != null && isComplete()) {
            currentState = AppliedState;
        } else {
            throw new ArgumentNullException ("Your application is incomplete");
            // some kind of error communication would probably be better
        }
    }

    public apply()    { currentState.apply(); }
    public review()   { currentState.review(); }
    public approve()  { currentState.approve(); }
    public decline()  { currentState.decline(); }

    //These could be done via an enum. I like enums!
    protected void setSubmittingState() {}
    protected void setApproveState() {}
    // etc. ...
}

// could be an interface if we don't have any default or base behavior.
public abstract class State {
    protected Application theApp;
    // maybe these return an object communicating errors / error state.
    public abstract void apply();
    public abstract void review();
    public abstract void accept();
    public abstract void decline();
}

public class Applied implements State {
    public Applied (Application newApp) {
        if(newApp != null)
            theApp = newApp;
        else
            throw new ArgumentNullException ("null application argument");
     }

    public override void apply() {
        // whatever is appropriate when already in "applied" state
        // do not do any work on behalf of other states!
        // throwing exceptions here is not appropriate, as others
        // have said.
      }

    public override void review() {
        if(recursiveBureaucracyBuckPassing())
            theApp.setReviewedState();
    }

    public override void decline() { // ditto  }
}

public class Reviewed implements State {}
public class Approved implements State {}
public class Declined implements State {}

Edit - Error Handling Comments

A recent comment:

...  if you are attempting to loan a book which is already issued to somebody else the Book model will contain the logic to prevent it's state from changing. This might be via a return value (e.g. a boolean successful yay/nay, or status code) or an exception (e.g. IllegalStateChangeException) or some other means. Irrespective of the means chosen, this aspect is not covered as part of this (or any) answer.

And from the original question:

But this kind of code does not make it obvious such a rule exists, it allows anyone to call update() method, and only after failing a client knows such operation was not permitted.

There is more design work to do. There is no Unified Field Theory Pattern. The confusion comes from assuming the state transition framework will do general application functions and error handling. That feels wrong because it is. The answer shown is designed for controlling state change.

Surely I can write an update() method in Application class, check Application state, and do nothing or throw exception if Application is not in required state

This suggests there are three functionalities working here: The State, Updating, and interaction of the two. In this case Application is not the code I've written. It may use it to determine current state. Application is not the applicationPaperwork either. Application is not the interaction of the two, but could be a general StateContextEvaluator class. Now Application will orchestrate these component interactions and then act accordingly, like emitting an error message.

End Edit


问:
How do you use duck typing in javascript without always checking for properties and methods?
I know javascript uses duck typing and at first I thought this would make polymorphism easy compared to strongly typed languages like C#. But now my functions that take arguments are littered with things like:

```<code>if(myObj.hasSomeProperty())
</code>```

or

```<code>if(myObj.hasSomeMethod())
</code>```

or

```<code>if(isNumber(myParam))
</code>```

etc.

This is really ugly to me. I come from a C# background and I find defined interfaces to be much better.

I'm wondering if I'm incorrectly attempting to apply strategies that are effective in statically typed languages and there's some better way to do this in javascript?

I know I could just not check, but tracking down javascript run time errors can be a nightmare since they don't always happen where the error is actually occurring in the code.

答:
How do you use duck typing in javascript without always checking for properties and methods?

Simple: don't always check for properties and methods.

In Ruby, what you are calling is called "chicken typing". In a dynamically duck-typed, language, you simply trust that the caller passes you a suitable object. It's the caller's job to honor his side of the contract.

I know javascript uses duck typing and at first I thought this would make polymorphism easy compared to strongly typed languages like C#.

You are confusing multiple orthogonal axis of typing here. There are four orthogonal axis of typing:

When: dynamic typing (types aren't known and checked until runtime) vs. static typing (types are known and checked before runtime)

What: duck typing (types are based on behavior), structural typing (types are based on structure), and nominal typing (types are based on name)

Can you see them? explicit typing (the types have to be explicitly annotated) vs. implicit typing (types are inferred)

strong typing vs. weak typing – you might have noticed that I didn't give this one a catchy title nor an explanation in parentheses, that's because unlike the seven terms above, which each have a single universally-accepted precise definition, these two terms have about a dozen semi-widely used vague definitions that contradict each other; ideally you should avoid these terms altogether, and if you must use them, precisely define them first

Since you mentioned C#: it is mostly statically typed, but supports dynamic typing through the type dynamic, it is mostly nominally typed, but anonymous types use structural typing, and syntactic patterns (such as LINQ query comprehension syntax) can be argued to be either duck-typed or structurally typed, it is mostly explicitly typed but supports implicit typing for generic type arguments and local variables (although the local variable case is rather strange compared to most other languages, because you cannot just leave the type out, instead you have to give it an explicit pseudo-type var, in other words, if you want an implicit type, you have to explicitly say so). Whether or not C# is strongly or weakly typed is a matter of which definition of the two terms you use, however, note that there can be plenty of runtime type errors in C#, especially because of unsafe array covariance.

I know I could just not check, but tracking down javascript run time errors can be a nightmare since they don't always happen where the error is actually occurring in the code.

Debugging is not an easy skill to learn. There are, however, techniques to make debugging easier, e.g. the Saff Squeeze is a technique described by Kent Beck which uses tests and refactoring for debugging:

Hit 'em High, Hit 'em Low:

Regression Testing and the Saff Squeeze

Kent Beck, Three Rivers Institute

Abstract: To effectively isolate a defect, start with a system-level test and progressively inline and prune until you have the smallest possible test that demonstrates the defect.


问:
Design decisions while porting a non object-oriented C program to Java
Background:
My boss made a comment on porting a C program that acts as some a simulator that communicates with a remote process through sockets to Java. He didn't assign it to me, or to anyone for that matter, it was just a project he had in mind. He showed and gave me access to the C source code file for said program so I could take a look.

Now I'm an intern in this company and haven't really been assigned something in particular so I wanted to start this project on my own and then show it to my boss.

Problem:
The C program is ~4k lines long. It consists on many global variables and functions that use those variables; I guess this is mainly to avoid passing many parameters. There are even some goto statements (yeah, also most of the codebase is from 1980). So basically my question is: should I aim to replicate the structure of the C program in a single Java class so there is a visible mapping of behavior between both? Or should I come up with
a better object oriented design that may imply the creation of many components? What would be your approach to solving this problem?

Thanks.

答:
I've dealt with a lot of these 80s C "vintage" codebases. If you want to hear some horror stories, I've dealt with ones where a single function was bigger than the entire codebase you're talking about (single functions that spanned over 20,000 lines of code with about 30 levels of indentation using a one-space indentation style and 50 or so variables declared at the top).

Even though your codebase is so teeny in size, I recommend approaching it from a thorough test-oriented perspective if the code is really complex in a way where you kind of need to reverse engineer it. Of course if you feel like you can reconstruct the program in Java without this kind of reverse engineering process, this might be a case where it's excusable to kind of start a new canvas from scratch.

If it is complex though and you don't feel confident that you can replicate the original software's functionality easily then...

Wrap In C to Desired Interface

Even C allows object-oriented programming. You can model objects like this (C++):

```<code>class Foo
{
public:
   Foo();
   ~Foo();
   void do_something(int blah);

private:
    float x;
    int y;
};
</code>```

... in C like so:

```<code>// In header file:
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);
void foo_do_something(struct Foo* foo, int blah);

// In source file:
struct Foo
{
    float y;
    int x;
};
...
</code>```

... there are even ways to emulate inheritance and polymorphism through composition and function pointers.

With this strategy, you can start extracting C interfaces over this messy blob of code which are well-designed, conform to SOLID principles, etc.

I recommend this strongly over the temptation to refactor the code directly where the iterations might start to seem endless as you get knee-deep in implementation details while simultaneously trying to find a sane structure out of it. Boldly create wrapper interfaces instead which model your final Java interface goals right from the start.

You could also potentially wrap this code into C++ classes given the ease of interoperability between C and C++ which might make it even easier to port this to Java. The initial versions might be stateless and just call functions in the C codebase if they're based on a bunch of globals, but don't let that impact your interface designs. Design them like they have encapsulated state.

Focus on getting the public interfaces right. You can do all kinds of inefficient trickery under the hood to make these interfaces work against this convoluted codebase. The initial goal here is to reshape the design and structure, not implementation (that comes last).

Write Tests for New Wrappers

Now write tests for these wrapper interfaces you construct, making sure they conform to your interface requirements. You also want to apply possibly a more integrated mindset here testing for correct output. The process of constructing these tests and wrapper interfaces will also rapidly accelerate your understanding of how the legacy code works.

Keep going until you've covered the entire codebase and established an acceptable structure, translating things on the way. The result should be a public interface which is suitable to you. Then start porting the client code in your codebase to start utilizing these interfaces.

Port to Java

Last but not least, port this to Java and replicate the same interfaces and tests. At this point, you should have a good enough understanding to fill in the implementations.

This is a very long and exhaustive route to solving the problem, but it shouldn't take that long given the teeny size of this codebase. I ended up doing this kind of stuff for millions upon millions of lines of code, so this should seem like a vacation in comparison.

Alternate Approach

An alternate approach mentioned already is just start off from the Java side. The reason I recommend starting off wrapping and testing from the C side is that I'm assuming the value of this convoluted piece of code relates to the outputs it provides over a given set of inputs. It can increase the rate at which you learn and understand the program by wrapping and testing it initially in the same language it was originally written, albeit very roundabout, and also makes sure your tests don't miss some subtle behavior in the original which might need to be preserved.

Body:
I've dealt with a lot of these 80s C "vintage" codebases. If you want to hear some horror stories, I've dealt with ones where a single function was bigger than the entire codebase you're talking about (single functions that spanned over 20,000 lines of code with about 30 levels of indentation using a one-space indentation style and 50 or so variables declared at the top).

Even though your codebase is so teeny in size, I recommend approaching it from a thorough test-oriented perspective if the code is really complex in a way where you kind of need to reverse engineer it. Of course if you feel like you can reconstruct the program in Java without this kind of reverse engineering process, this might be a case where it's excusable to kind of start a new canvas from scratch.

If it is complex though and you don't feel confident that you can replicate the original software's functionality easily then...

Wrap In C to Desired Interface

Even C allows object-oriented programming. You can model objects like this (C++):

class Foo
{
public:
   Foo();
   ~Foo();
   void do_something(int blah);

private:
    float x;
    int y;
};

... in C like so:

// In header file:
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);
void foo_do_something(struct Foo* foo, int blah);

// In source file:
struct Foo
{
    float y;
    int x;
};
...

... there are even ways to emulate inheritance and polymorphism through composition and function pointers.

With this strategy, you can start extracting C interfaces over this messy blob of code which are well-designed, conform to SOLID principles, etc.

I recommend this strongly over the temptation to refactor the code directly where the iterations might start to seem endless as you get knee-deep in implementation details while simultaneously trying to find a sane structure out of it. Boldly create wrapper interfaces instead which model your final Java interface goals right from the start.

You could also potentially wrap this code into C++ classes given the ease of interoperability between C and C++ which might make it even easier to port this to Java. The initial versions might be stateless and just call functions in the C codebase if they're based on a bunch of globals, but don't let that impact your interface designs. Design them like they have encapsulated state.

Focus on getting the public interfaces right. You can do all kinds of inefficient trickery under the hood to make these interfaces work against this convoluted codebase. The initial goal here is to reshape the design and structure, not implementation (that comes last).

Write Tests for New Wrappers

Now write tests for these wrapper interfaces you construct, making sure they conform to your interface requirements. You also want to apply possibly a more integrated mindset here testing for correct output. The process of constructing these tests and wrapper interfaces will also rapidly accelerate your understanding of how the legacy code works.

Keep going until you've covered the entire codebase and established an acceptable structure, translating things on the way. The result should be a public interface which is suitable to you. Then start porting the client code in your codebase to start utilizing these interfaces.

Port to Java

Last but not least, port this to Java and replicate the same interfaces and tests. At this point, you should have a good enough understanding to fill in the implementations.

This is a very long and exhaustive route to solving the problem, but it shouldn't take that long given the teeny size of this codebase. I ended up doing this kind of stuff for millions upon millions of lines of code, so this should seem like a vacation in comparison.

Alternate Approach

An alternate approach mentioned already is just start off from the Java side. The reason I recommend starting off wrapping and testing from the C side is that I'm assuming the value of this convoluted piece of code relates to the outputs it provides over a given set of inputs. It can increase the rate at which you learn and understand the program by wrapping and testing it initially in the same language it was originally written, albeit very roundabout, and also makes sure your tests don't miss some subtle behavior in the original which might need to be preserved.


问:
Why does an immutable object in Scala need less memory than a mutable one?
In Programming in Scala, there is this statement:

For instance an empty mutable map in its default representation of HashMap takes up about 80 bytes and about 16 more are added for each entry that’s added to it. An empty immutable Map is a single object that’s shared between all references, so referring to it essentially costs just a single pointer field.

Why does a mutable map need more space?

答:
You've pretty much answered your own question here: the immutable object can be shared between every identical instance of the object, but the mutable one can't because that would mean things go horribly wrong when you add anything to the map.

In theory, the mutable object could have been implemented with copy-on-write semantics which would allow sharing of identical mutable maps, but that isn't the route Scala decided to go down.


问:
Doesn't "always initialize variables" lead to important bugs being hidden?
The C++ Core Guidelines have the rule ES.20: Always initialize an object.

Avoid used-before-set errors and their associated undefined behavior. Avoid problems with comprehension of complex initialization. Simplify refactoring.

But this rule doesn't help to find bugs, it only hides them.

Let's suppose that a program has an execution path where it uses an uninitialized variable. It is a bug. Undefined behavior aside, it also means that something went wrong, and the program probably doesn't meet its product requirements. When it will be deployed to production, there can be a money loss, or even worse.

How do we screen bugs? We write tests. But tests don't cover 100% of execution paths, and tests never cover 100% of program inputs. More than that, even a test covers a faulty execution path - it still can pass. It's undefined behavior after all, an uninitialized variable can have a somewhat valid value.

But in addition to our tests, we have the compilers which can write something like 0xCDCDCDCD to uninitialized variables. This slightly improves detection rate of the tests.

Even better - there are tools like Address Sanitizer, which will catch all the reads of uninitialized memory bytes.

And finally there are static analyzers, which can look at the program and tell that there is a read-before-set on that execution path.

So we have many powerful tools, but if we initialize the variable - sanitizers find nothing.

```<code>int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.

// Another bug: use empty buffer after read error.
use(buffer);
</code>```

There is another rule - if program execution encounters a bug, program should die as soon as possible. No need to keep it alive, just crash, write a crashdump, give it to the engineers for investigation.

Initializing variables unnecessarily does the opposite - program is being kept alive, when it would already get a segmentation fault otherwise.

答:
Your reasoning goes wrong on several accounts:

Segmentation faults are far from certain to occur. Using an uninitialized variable results in undefined behaviour. Segmentation faults are one way that such behaviour can manifest itself, but appearing to run normal is just as likely.

Compilers never fill the uninitialized memory with a defined pattern (like 0xCD). This is something that some debuggers do to assist you in finding places where uninitialized variables get used. If you run such a program outside a debugger, then the variable will contain completely random garbage. It is equally likely that a counter like the bytes_read has the value 10 as that it has the value 0xcdcdcdcd.

Even if you are running in a debugger that sets the uninitialized memory to a fixed pattern, they only do so at startup. This means that this mechanism only works reliably for static (and possibly heap-allocated) variables. For automatic variables, which get allocated on the stack or live only in a register, the chances are high that the variable is stored in a location that was used before, so the tell-tale memory pattern has already been overwritten.

The idea behind the guidance to always initialize variables is to enable these two situations

The variable contains a useful value right from the very beginning of its existence. If you combine that with the guidance to declare a variable only once you need it, you can avoid future maintenance programmers falling in the trap of starting to use a variable between its declaration and the first assignment, where the variable would exist but be uninitialized.

The variable contains a defined value that you can test for later, to tell if a function like my_read has updated the value. Without initialization, you can't tell if bytes_read actually has a valid value, because you can't know what value it started with.


答:
You wrote "this rule doesn't help to find bugs, it only hides them" - well, the goal of the rule is not to help finding bugs, but to avoid them. And when a bug is avoided, there is nothing hidden.

Lets dicuss the issue in terms of your example:  suppose the my_read function has the written contract to initialize bytes_read under all circumstances, but it does not in case of an error, so it is faulty, at least, for this case. Your intention is to use the run time environment to show that bug by not initializing the bytes_read parameter first. As long as you know for sure there is an address sanitizer in place, that is a indeed a possible way to detect such a bug. To fix the bug, one has to change the my_read function internally.

But there is a different point of view, which is at least equally valid: the faulty behaviour only emerges from the combination of not initializing bytes_read beforehand, and calling my_read afterwards (with the expectation bytes_read is initialized after that). This is a situation which will happen often in real world components when the written spec for a function like my_read is not 100% clear, or even wrong about the behaviour in case of an error. However, as long bytes_read is initialized to zero before the call, the program behaves the same way as if the initialization was done inside my_read, so it behaves correctly, in this combination there is no bug in the program.

So my recommendation that follows from that is: use the non-initializing approach only if

you want to test if a function or code block initializes a specific parameter

you are 100% sure the function in stake has a contract where it is definitely wrong not to assign a value to that parameter

you are 100% sure the environment can catch this

These are conditions you can typically arrange in test code, for a specific tooling environment.

In production code, however, better always initialize such a variable beforehand, it is the more defensive approach, which prevents bugs in case the contract is incomplete or wrong, or in case the address sanitizer or similar safety measures are not activated. And the "crash-early" rule applies, as you correctly wrote, if program execution encounters a bug. But when initializing a variable beforehand means there is nothing wrong, then there is no need to stop further execution.

Title: Doesn't "always initialize variables" lead to important bugs being hidden?

Body:
The C++ Core Guidelines have the rule ES.20: Always initialize an object.

Avoid used-before-set errors and their associated undefined behavior. Avoid problems with comprehension of complex initialization. Simplify refactoring.

But this rule doesn't help to find bugs, it only hides them.

Let's suppose that a program has an execution path where it uses an uninitialized variable. It is a bug. Undefined behavior aside, it also means that something went wrong, and the program probably doesn't meet its product requirements. When it will be deployed to production, there can be a money loss, or even worse.

How do we screen bugs? We write tests. But tests don't cover 100% of execution paths, and tests never cover 100% of program inputs. More than that, even a test covers a faulty execution path - it still can pass. It's undefined behavior after all, an uninitialized variable can have a somewhat valid value.

But in addition to our tests, we have the compilers which can write something like 0xCDCDCDCD to uninitialized variables. This slightly improves detection rate of the tests.

Even better - there are tools like Address Sanitizer, which will catch all the reads of uninitialized memory bytes.

And finally there are static analyzers, which can look at the program and tell that there is a read-before-set on that execution path.

So we have many powerful tools, but if we initialize the variable - sanitizers find nothing.

```<code>int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.

// Another bug: use empty buffer after read error.
use(buffer);
</code>```

There is another rule - if program execution encounters a bug, program should die as soon as possible. No need to keep it alive, just crash, write a crashdump, give it to the engineers for investigation.

Initializing variables unnecessarily does the opposite - program is being kept alive, when it would already get a segmentation fault otherwise.


答:
Sharing is only part of the answer.

The mutable map has to contain all the fields which will be needed when/if elements are added, since calling methods can't change the class of the object.

With immutable maps, you can have a special class for empty maps, which doesn't need any fields (except the ones it inherits), while single-entry maps have a field for the key and a field for the value and can access them without any extra indirections. Calling methods which add elements just returns a new object of a different class, which isn't a problem.

Title: Why does an immutable object in Scala need less memory than a mutable one?

Body:
In Programming in Scala, there is this statement:

For instance an empty mutable map in its default representation of HashMap takes up about 80 bytes and about 16 more are added for each entry that’s added to it. An empty immutable Map is a single object that’s shared between all references, so referring to it essentially costs just a single pointer field.

Why does a mutable map need more space?


问:
Can objects be implemented in terms of higher order functions?
Martin Odersky finished one online course on Scala with an unanswered question:

Can we implement one concept in terms of other ?

Objects in terms of higher order functions?

Higher order functions in terms of objects?

It is clear that high order functions can be implemented using objects but I am not sure if it works the other way round or at least while using static types.

Suppose that closure can contain encapsulated data as object does but it still has only one 'method' in its interface - applying itself. In dynamic languages (or in static ones if we use some broad type like Object or Any) we can pass and return anything from this function but is this really an object ?

答:
Effectively, yes. Closures and objects are equivalent. Higher order functions are a bit more debatable. Without closure over local variables (or if local variables are immutable in your language), there can be no mutable fields in the pseudo-object. If you can only get immutable sort-of objects, then it is more easily argued that they are not like objects.

But from a conceptual standpoint, you should generally think of closures and objects as similar beasties. In C# for example, closures are implemented via classes. I would expect Scala to do the same.


答:
You can think of an object as a closure that closes over the member variables of the object and, each time it is invoked with a method name, it returns a method implementation. You can then apply the returned method implementation on the actual method arguments.

Since the result of this closure is a procedure / function (a method implementation), it is indeed a higher-order function: a higher-order function is a function that either takes functions as input arguments or returns a function as a result.

Title: Can objects be implemented in terms of higher order functions?

Body:
Martin Odersky finished one online course on Scala with an unanswered question:

Can we implement one concept in terms of other ?

Objects in terms of higher order functions?

Higher order functions in terms of objects?

It is clear that high order functions can be implemented using objects but I am not sure if it works the other way round or at least while using static types.

Suppose that closure can contain encapsulated data as object does but it still has only one 'method' in its interface - applying itself. In dynamic languages (or in static ones if we use some broad type like Object or Any) we can pass and return anything from this function but is this really an object ?


答:
With dynamic typing, it is fairly straightforward to implement an object-oriented system in terms of closures. I've written about this in my answer to “Modelling Objects as Functions” and expanded on that on my blog. There are some details about open recursion that are necessary to get certain OOP features such as subclassing right, but it's doable. In short, invoking the closure representing an object maps a method name to a method bound to that object, which can then be invoked as an ordinary function. Usage might look like result = object("methodName")(otherObject).

However, OOP and static typing are fundamentally at odds. There are various interpretations of OOP, such as OOP-as-message-passing or OOP-as-virtual-dispatch, but a central theme is that we do not statically know the exact runtime type of an expression such as x. However, many statically typed OOP languages do assign type bounds to an expression (such as x is a subtype of Iterable). When implementing objects in terms of closures in a statically typed language, we quickly run into the problem – when specifying the required method as an argument to the dispatch function, we can't statically know the required signature of the function. In the above example, how do I know that the result of object("methodName") should be a function accepting exactly one parameter?

The common solution when implementing objects is to make the object-system unityped (aka. untyped). That is, all method signatures would have the same type regardless of their arity (number of arguments) or of the types of arguments. This also requires that all our objects have the same type in the host language.

Some languages might be able to do better. E.g. in C++, we could pass the requested method type as a template parameter to the dispatch function: auto result = object<ResultType(ArgumentType)>("methodName")(otherObject). A clever implementation could then use different lookup tables to dispatch int() or int(int) method types etc. However, we cannot statically guarantee that the requested method exists since it is provided as a string. Another possibility would be to pass in a (visitor-like?) Message object rather than a string name to the dispatch function, which might allow more type safety in statically typed host languages, but I do not have sufficient experience with implementing OOP in static languages to describe this in more detail.


问:
Do you apply a code of conduct on accepting jobs, projects or requirements?
When writing software for yourself, your company or third parties, do you always consider certain principles, values, standards, or rules of behavior that guide the decisions, procedures and systems in a way that contributes to the welfare of its key stakeholders, and respects the rights of all constituents affected by its operations?

And can this code of conduct sometimes be overruled by business requirements, lack of technical skills or other friction during the development process?

Some random examples in order of severity. (yes that is controversial) :

Do you accept known bugs as a risk for the end-user?

When writing applications, do you always give the end user the chance for a complete de-install?

Do you always secure and encrypt private data delivered end-users in your web application?

Do you alwask ask the end-user before submitting his entered data to the server?

Did you ever wrote an application that sends unwanted e-mails?

Did you ever work on harvesting or scraping projects only for the benefit of the business?

Did you ever write software that is legal but moraly controversial, like  for weapons industry.

Did you ever wrote software that ( can intentionally) or is be used for criminal activities

It would be nice if you can get a good case with explanation on your moral and ethical decisions.

note: Since ethics and law are quite local and cultural dependent, it would be interesting if you add the location of the "crime scene" with it.

答:
Overall, I always keep the Software Engineering Code of Ethics in mind. However, to address some of your particular points:

Do you accept known bugs as a risk for the end-user?

It depends. If it's a mission critical system and the bug is a showstopper, that's unacceptable. However, if it's a minor flaw that has workarounds in a non-critical system, that's acceptable. I always consider the impact of the problem on the system and to the users (and people affected by) the system.

Do you always secure and encrypt private data delivered end-users in your web application?

If I was on a project where this applied, I would consult any applicable laws and guidelines and follow them. If there were no applicable guidelines, I would err on the side of caution and use some form of security. Of course, you have to weigh a number of factors, ranging from how the system is deployed (physical locations, connections between nodes) and performance of any algorithms or techniques used.

Did you ever write software that is legal but morally controversial, like for weapons industry.

All of my jobs (as you can see in my profile) have been in the defense industry (and I'm also planning on working in the defense or intelligence industries after graduation), including work on ISR systems and Command and Control systems. I don't understand anyone, especially really good software engineers with skills that these projects need, who says that they won't build such systems. The way I see it, by bringing the best software engineering practices to these systems, you are only making them safer and more reliable. And these systems that involve life and death need to be as safe and reliable as possible.

ContentLicense: CC BY-SA 2.5


答:
I mostly work in a functional programming language where you aren't allowed to reassign variables.  Ever.  That completely eliminates this class of bugs.  This seemed like a huge restriction at first, but it forces you to structure your code in a way that is consistent with the order you learn new data, which tends to simplify your code and make it easier to maintain.

Those habits can be carried over into imperative languages as well.  It is nearly always possible to refactor your code to avoid initializing a variable with a dummy value.  That's what those guidelines are telling you to do.  They want you to put something meaningful in there, not something that will just make automated tools happy.

Your example with a C-style API is a little more tricky.  In those cases, when I use the function I'll initialize to zero to keep the compiler from complaining, but one time in the my_read unit tests, I'll initialize to something else to make sure the error condition works properly.  You don't need to test every possible error condition upon every use.


问:
How likely are collisions of timestamp-based identifiers?
I overheard a discussion about using timestamps as unique identifiers when storing some data in a database. Person A pointed out that there's a risk of collisions. Person B replied that it's very unlikely to happen with the identifier generation rates at question.

My question is: how likely is it?  Is there a way to estimate the probability of getting a collision, or the amount of collisions you're going to get in some timespan?

I'm interested in both theoretical and practical answers.

答:
Consider that for any precision of a time-based ID, you could use the same data type to store a simple counter.  This will always accommodate at least as many records as a time-based ID, and probably many more, since the time-based ID wastes potential IDs for every unit of timer resolution in which an ID is not generated.

If the timestamp is meaningful, you could save it separately.  In looking for a citation to explain why primary keys should always be arbitrary, I discovered that this is more controversial than I realized; I thought it was settled twenty years ago.  Suffice it to say that there are important advantages to using arbitrary, a.k.a. surrogate IDs.


答:
Firstly, why aren't you using a counter? Usually that's all you need.

Secondly, you should use uuids rather than timestamps. They've solved this problem, and there is no really no good reason for you to try to solve it yourself, potentially opening yourself up to problems.

Thirdly, the calculation you should do is called the birthday problem. The original birthday problem asks how likely it is that two people in a group share a birthday. It should be clear this is pretty much the same as asking how likely it is that two timestamps where generated at the same millisecond (or whatever granularity).

As it turns out, you only need 23 people for the probability of a shared birthday to exceed 50%. This is much less than most people expect (hence sometimes being called the birthday paradox). It's also why there's a good chance that collisions are more likely than you are expecting.

You can read about how to compute it on Wikipedia or use the online calculator at WolfromAlpha:

Just to give an example, if you generate 10 ids a second with a granularity of milliseconds, the probability of a collision is 1 in 23. On average, you'll have a collision every 23 seconds.

But it's worse than that. The assumption in this math is that every possible birthday is equally likely. That's not true for birthdays, more people on born in the spring. It's also not going to be true for your timestamps. You are going to get much heavier on certain times of the day than others.

What's worst of all, is that a sudden increase of usage, resulting in a large increase of the chance of collisions is exactly the time you don't want a mysterious random failure like will result.

Don't use timestamps. Just don't. Use uuids which have been engineered by smart people to avoid the collision problem.

Title: How likely are collisions of timestamp-based identifiers?

Body:
I overheard a discussion about using timestamps as unique identifiers when storing some data in a database. Person A pointed out that there's a risk of collisions. Person B replied that it's very unlikely to happen with the identifier generation rates at question.

My question is: how likely is it?  Is there a way to estimate the probability of getting a collision, or the amount of collisions you're going to get in some timespan?

I'm interested in both theoretical and practical answers.


问:
Which algorithm is performant for matrix multiplication of 4x4 matrices of affine transformations
I am wondering what is a good, performant algorithm for matrix multiplication of 4x4 matrices. I am implementing some affine transformations and I am aware that there are several algorithms for efficient matrix multiplication, like Strassen. But are there some algorithms that are especially efficient for matrices that small? Most sources I had a glance at are looking at which are asymptotically the most efficient.</p>

答: Often, simple algorithms are the fastest for very small sets, because more complex algorithms usually use some transformation that add some overhead. I think your best bet is not on a more efficient algorithm (I think most libraries use straightforward methods), but on a more efficient implementation, for example, one using SIMD extensions (assuming x86 or amd64 code), or hand-written in assembly. Also, the memory layout should be well thought out. You should be able to find enough resources on this.</p>

ContentLicense: CC BY-SA 4.0


答:
Person A pointed out that there's a risk of collisions. Person B replied that it's very unlikely to happen with the identifier generation rates at question.

Both may be correct for right now, but it isn't right now you care about so much.  It's what happens later that will do you in.  What happens when the rate you're generating rows increases?  What will you do when someone who provided you with a batch of data comes back and says they need to adjust the times because their clocks were wrong and the new values overlap with those of other rows?

B is essentially admitting that it's impossible to guarantee that a collision won't happen.  If he can't make that guarantee, he can't guarantee his system will function correctly and will be sent back to the drawing board to come up with a scheme for dealing with them.  After coming up with one without the same risks (very likely to involve the counter B doesn't want to use), the rate they occur no longer matters.

Is there a way to estimate the probability of getting a collision, or the amount of collisions you're going to get in some timespan?

Given enough information, sure, but there are a lot of things that would be very difficult to quantify in a way that will give you a meaningful answer.

Alan Kay famously said that the best way to predict the future is to invent it.  I'm going to twist that a bit and say that the best way to estimate the probability of a collision is to force it to zero.  In this case, that means using the guaranteed-unique primary keys provided by any database worth it salt.  Unless you can make an awfully strong case against the extra space required to store them, you're better off going that route instead of a too-clever-by-half solution that tries to embed intelligence into what should be essentially a random number.


问:
Authorization and Authentication using multiple types of authentication in MVC
Currently I am managing a team where we're building a new SaaS application.

The way it is currently structured is that we have a solution that has our business logic and data, and a solution that holds our website (and related projects)

In our current user base, there are clients that use different types of authentication:

username/password using the aspnet membership architecture

Homegrown SOAP web services that allow a developer to connect via SSO

SAML

Clients may have different settings for logging in, but users within the clients log in the same way.  The big challenge with our legacy system is that these are somewhat 'hacked' together and very hard to manage.  I want to make sure we are much more scalable for the future.

I've looked into claims-based authentication using the MVC framework and understand that pretty well, so I'm confident our team can build the framework to support it.  My challenge is with the STS (identity server), so I have a few questions:

Fundamentally, am I going in the right direction?

What system owns the knowledge of where a user should be authenticated? I would suspect the STS because that would mean the claims-based system can truly not worry about authentication or authorization

I've looked into OpenAM, OpenIDM and IdentityServer for the STS, but cannot really figure out how to plug them in.  Are these even STS systems?

I am willing to spend money on a solution as well, is there any other solutions I should be looking into?

答:
This has been sitting for a while, and I figured to answer my own question since we've solved this problem by now...

We decided to convince those clients that were using the homegrown SOAP services to utilize SAML, and we partnered with Ping Identity to help us out with the SAML component as we weren't experts.

As for our design, we were able to keep it relatively simple: Some SAML clients were also in need of a username/password authentication type for certain users, so we designed both a connection for SAML as well as for username and password.

We also decided to go with an IdP only approach, which so far, hasn't been an issue.


答:
Always initialize your variables

The difference between the situations you are considering is that the case without initialization results in undefined behavior, while the case where you took the time to initialize creates a well defined and deterministic bug.  I cannot stress how extremely different these two cases are enough.

Consider a hypothetical example which may have happened to a hypothetical employee on a hypothetical simulations program.  This hypothetical team was hypothetically trying to make a deterministic simulation to demonstrate that the product they were hypothetically selling met needs.

Okay, I'll stop with the word injections.  I think you get the point ;-)

In this simulation, there were hundreds of uninitialized variables.  One developer ran valgrind on the simulation and noticed there were several "branch on uninitialized value" errors.  "Hmm, that looks like that could cause non-determinism, making it hard to repeat test runs when we need it most."  The developer went to management, but management was on a very tight schedule, and couldn't spare resources to track down this issue. "We end up initializing all of our variables before we use them.  We have good coding practices."

A few months before the final delivery, when the simulation is in full churn mode, and the entire team is sprinting to finish all the things management promised on a budget that, like every project ever funded, was too small.  Someone noticed that they couldn't test an essential feature because, for some reason, the deterministic sim wasn't behaving deterministically to debug.

The entire team may have been halted and spent the better part of 2 month combing the entire simulation codebase fixing uninitialized value errors instead of implementing and testing features.  Needless to say, the employee skipped the "I told you so's" and went straight into helping other developers understand what uninitialized values are.  Strangely enough, the coding standards were changed shortly after this incident, encouraging developers to always initialize their variables.

And this is the warning shot.  This is the bullet that grazed across your nose.  The actual issue is far far far far far more insidious than you even imagine.

Using an uninitialized value is "undefined behavior" (except for a few corner cases such as char).  Undefined behavior (or UB for short) is so insanely and completely bad for you, that you should never ever ever believe it is better than the alternative.  Sometimes you can identify that your particular compiler defines the UB, and then its safe to use, but otherwise, undefined behavior is "any behavior the compiler feels like."  It may do something you'd call "sane" like have an unspecified value.  It may emit invalid opcodes, potentially causing your program to corrupt itself.  It may trigger a warning at compile time, or the compiler may even consider it an error outright.

Or it may do nothing at all

My canary in the coal mine for UB is a case from a SQL engine that I read about.  Forgive me for not linking it, I've failed to find the article again.  There was a buffer overrun issue in the SQL engine when you passed a larger buffer size to a function, but only on a particular version of Debian.  The bug got dutifully logged, and explored.  The funny part was: the buffer overrun was checked.  There was code to handle the buffer overrun in place.  It looked something like this:

```<code>// move the pointers properly to copy data into a ring buffer.
char* putIntoRingBuffer(char* begin, char* end, char* get, char*put, char* newData, unsigned int dataLength)
{
    // If dataLength is very large, we might overflow the pointer
    // arithmetic, and end up with some very small pointer number,
    // causing us to fail to realize we were trying to write past the
    // end.  Check this before we continue
    if (put + dataLength < put)
    {
        RaiseError("Buffer overflow risk detected");
        return 0;
    }
    ...
    // typical ring-buffer pointer manipulation followed...
}
</code>```

I've added more comments in my rendition, but the idea is the same.  If put + dataLength wraps around, it will be smaller than the put pointer (they had compile time checks to make sure unsigned int was the size of a pointer, for the curious).  If this happens, we know the standard ring buffer algorithms might get confused by this overflow, so we return 0.  Or do we?

As it turns out, overflow on pointers is undefined in C++.  Because most compilers are treating pointers as integers, we end up with typical integer overflow behaviors, which happen to be the behavior we want.  However, this is undefined behavior, meaning the compiler is allowed to do anything it wants.

In the case of this bug, Debian happened to choose to use a new version of gcc that none of the other major Linux flavors had updated to in their production releases.  This new version of gcc had a more aggressive dead-code optimizer.  The compiler saw the undefined behavior, and decided the result of the if statement would be "whatever makes the code optimization best," which was an absolutely legal translation of UB.  Accordingly, it made the assumption that since ptr+dataLength can never be below ptr without a UB pointer overflow, the if statement would never trigger, and optimized out the buffer overrun check.

The use of "sane" UB actually caused a major SQL product to have a buffer overrun exploit that it had written code to avoid!

Never rely on undefined behavior.  Ever.

Body:
Always initialize your variables

The difference between the situations you are considering is that the case without initialization results in undefined behavior, while the case where you took the time to initialize creates a well defined and deterministic bug.  I cannot stress how extremely different these two cases are enough.

Consider a hypothetical example which may have happened to a hypothetical employee on a hypothetical simulations program.  This hypothetical team was hypothetically trying to make a deterministic simulation to demonstrate that the product they were hypothetically selling met needs.

Okay, I'll stop with the word injections.  I think you get the point ;-)

In this simulation, there were hundreds of uninitialized variables.  One developer ran valgrind on the simulation and noticed there were several "branch on uninitialized value" errors.  "Hmm, that looks like that could cause non-determinism, making it hard to repeat test runs when we need it most."  The developer went to management, but management was on a very tight schedule, and couldn't spare resources to track down this issue. "We end up initializing all of our variables before we use them.  We have good coding practices."

A few months before the final delivery, when the simulation is in full churn mode, and the entire team is sprinting to finish all the things management promised on a budget that, like every project ever funded, was too small.  Someone noticed that they couldn't test an essential feature because, for some reason, the deterministic sim wasn't behaving deterministically to debug.

The entire team may have been halted and spent the better part of 2 month combing the entire simulation codebase fixing uninitialized value errors instead of implementing and testing features.  Needless to say, the employee skipped the "I told you so's" and went straight into helping other developers understand what uninitialized values are.  Strangely enough, the coding standards were changed shortly after this incident, encouraging developers to always initialize their variables.

And this is the warning shot.  This is the bullet that grazed across your nose.  The actual issue is far far far far far more insidious than you even imagine.

Using an uninitialized value is "undefined behavior" (except for a few corner cases such as char).  Undefined behavior (or UB for short) is so insanely and completely bad for you, that you should never ever ever believe it is better than the alternative.  Sometimes you can identify that your particular compiler defines the UB, and then its safe to use, but otherwise, undefined behavior is "any behavior the compiler feels like."  It may do something you'd call "sane" like have an unspecified value.  It may emit invalid opcodes, potentially causing your program to corrupt itself.  It may trigger a warning at compile time, or the compiler may even consider it an error outright.

Or it may do nothing at all

My canary in the coal mine for UB is a case from a SQL engine that I read about.  Forgive me for not linking it, I've failed to find the article again.  There was a buffer overrun issue in the SQL engine when you passed a larger buffer size to a function, but only on a particular version of Debian.  The bug got dutifully logged, and explored.  The funny part was: the buffer overrun was checked.  There was code to handle the buffer overrun in place.  It looked something like this:

// move the pointers properly to copy data into a ring buffer.
char* putIntoRingBuffer(char* begin, char* end, char* get, char*put, char* newData, unsigned int dataLength)
{
    // If dataLength is very large, we might overflow the pointer
    // arithmetic, and end up with some very small pointer number,
    // causing us to fail to realize we were trying to write past the
    // end.  Check this before we continue
    if (put + dataLength < put)
    {
        RaiseError("Buffer overflow risk detected");
        return 0;
    }
    ...
    // typical ring-buffer pointer manipulation followed...
}

I've added more comments in my rendition, but the idea is the same.  If put + dataLength wraps around, it will be smaller than the put pointer (they had compile time checks to make sure unsigned int was the size of a pointer, for the curious).  If this happens, we know the standard ring buffer algorithms might get confused by this overflow, so we return 0.  Or do we?

As it turns out, overflow on pointers is undefined in C++.  Because most compilers are treating pointers as integers, we end up with typical integer overflow behaviors, which happen to be the behavior we want.  However, this is undefined behavior, meaning the compiler is allowed to do anything it wants.

In the case of this bug, Debian happened to choose to use a new version of gcc that none of the other major Linux flavors had updated to in their production releases.  This new version of gcc had a more aggressive dead-code optimizer.  The compiler saw the undefined behavior, and decided the result of the if statement would be "whatever makes the code optimization best," which was an absolutely legal translation of UB.  Accordingly, it made the assumption that since ptr+dataLength can never be below ptr without a UB pointer overflow, the if statement would never trigger, and optimized out the buffer overrun check.

The use of "sane" UB actually caused a major SQL product to have a buffer overrun exploit that it had written code to avoid!

Never rely on undefined behavior.  Ever.


答:
I think you are doing the right thing, you just need to find the style that will be more pleasing to your eye. Here are some ideas:

Instead of if(myObj.hasSomeProperty()) you could use if( myobj.prop !== undefined ). This, BTW will work only in non-strict mode, in strict mode you'd have to use if( typeof myobj.prop !== 'undefined' ).

You can offload some of the type checking to separate validators. This has the benefit of being able to skip validation once the interfaces are mature, e.g. if( is_valid( myobject )), where is_valid begins with if( !DEBUG ) return true;.

Sometimes it makes sense to clone input into a canonical form, in which case you could collect the various validation targets into the cloning function/object. For exmaple, in my_data = Data( myobj, otherstuff ) the Data constructor could conveniently run all the various validations in a central place.

You could use some library that will (at a performance toll) streamline your type validation into something more elegant. Even if you won't take this route in the long term you may find it comfortable to get you smoothly into your own style. Some examples include xtype.js, type-check, validator.js, etc.

Title: How do you use duck typing in javascript without always checking for properties and methods?

Body:
I know javascript uses duck typing and at first I thought this would make polymorphism easy compared to strongly typed languages like C#. But now my functions that take arguments are littered with things like:

```<code>if(myObj.hasSomeProperty())
</code>```

or

```<code>if(myObj.hasSomeMethod())
</code>```

or

```<code>if(isNumber(myParam))
</code>```

etc.

This is really ugly to me. I come from a C# background and I find defined interfaces to be much better.

I'm wondering if I'm incorrectly attempting to apply strategies that are effective in statically typed languages and there's some better way to do this in javascript?

I know I could just not check, but tracking down javascript run time errors can be a nightmare since they don't always happen where the error is actually occurring in the code.


答:
I know I could just not check, but tracking down javascript run time
  errors can be a nightmare since they don't always happen where the
  error is actually occurring in the code.

Indeed, the typical practice is not to check. And, yes, this does mean that you'll get javascript errors which are reported elsewhere from the actual problem. But in practice, I don't find this to be a big problem.

When working in javascript, I'm constantly testing what I'm writing. In most code, I've got unit tests which automatically run every time I save my editor. When something unexpectedly goes wrong, I know almost immediately. I've got a very small area of code in which I might have made the mistake, since it's almost always the last thing I touched that has the mistake.

When I do get a runtime error, I've at least got the stack trace, and in the case of an in-browser error I've got the ability to go to any level of the stack trace and inspect the variables. It's typically easy to trace back where the bad value came from, and thus trace it back to the original problem.

If you are like me when I wrote primarily in statically typed languages, I wrote larger blocks of code before testing and I didn't have practice in tracing back a value where it came from. Programming in a language like javascript is different, you have to use different skills. I suspect programming like that seems way harder, because those aren't the skills you've developed working in other languages like C#.

Having said that, I think there is a lot to be said for explicit types. They are great for documentation and catching errors early. I think in future we'll see increasing adoption of things like Flow and Typescript which add the static type checking to the javascript.


答: No, it doesn't hide bugs. Instead it makes behavior deterministic in a way such that if a user encounters an error, a developer can reproduce it.</p>


问:
Methods of separating front and back-end with full stack javascript?
Suppose I have a front-end which is mostly a single-page application written using angular, grunt, and bower.  And suppose I have a backend, which is mostly just a REST API sitting on top of an ORM, which stores/retrieves objects from a database, using things like grunt, express and sequelize.

The angular application does all of the visual stuff the user sees, but it does so by being a GUI over the services provided by the back-end.

It would be desirable to separate these into two different codebases, to permit independent development, versioning, continuous integration, push to development, etc.

My question is, what methods are out there for doing this cleanly?  Are there recommended best practices for full-stack javascript?

Option #1 seems to be a monolith, i.e. "don't separate them".  The pro is that the build chain is simple, and everything is in one place - but there seem to be many cons; harder to version independently, a broken front means an un-deployable back, and so on.

Option #2 seems to be a quasi-monolith, where the front-end build chain results in writing a bunch of files to the back-end.  The dist directory on the front-end would refer to some directory on the back-end, so essentially when the front end minifies, uglifies, etc, it ends up publishing to the back-end, which runs everything.

Option #3 seems full-separation: front-end and back-end each run their own servers on different ports, and they are fully separate projects.  The drawback seems that they need to be configured to know about each other's ports; the back-end must allow CORS from the front-end, and the front-end needs to know where all those endpoints are expected to be.

Option #4 might be to use something like docker-compose to rig the whole thing together.

I'm sure there are other options.  What's the recommended best practice?

答:
It's a front-end, back-end application, with a REST interface in between. You already have full separation.

My vote is for option # 3.  You seem worried about configuration, but that's kinda the whole point.  Configuration allows you to have full separation without requiring tightly-coupled code bindings.  If you're worried about CORS, put everything on one domain.  If you must have CORS, the best way to manage that is a configuration.

But there is no "best practice" here.  The best practice is the one that is going to best meet your specific needs.


问:
Strategies to maintain contract between mocks and APIs
Using a mock instead of hitting a 3rd party API like Postgres or Stripe can often be necessary when writing tests. A problem I've seen is when the API can unknowingly diverges from the data the mocks return. How can I maintain the contract between test data and real APIs? This is a Javascript project.</p>

答:
Great question, this is a very common problem when working with commercial third parties that we don't have access to.

First, always write your integration tests against the real API when possible.

If this is not feasible, try to get a sample of real data returned by the API and build your mocks based on it.  Get multiple samples that represent different scenarios, make sure cover general and edge cases.

If real data is not available, it's time for you to start thinking. Do your research first, try to see what other similar APIs return. Also, ask yourself the following questions:

What's the data for?

Who will be using it?

How will it be stored/displayed?

What constraints will I find?

Data types?

Try to come up with a "valid" data model that you think it will be close to the real one. Again, make sure you cover as many scenarios as you can think of.

Spending time on making your mocks as real as possible is worth the effort, it can save you a lot of time and trouble when your start querying the API.

Hope you find this helpful.