4

So, there are some good answers to this question, namely: Why is Global State so Evil?

I have a specific question about the alternatives Mikera proposed as the answer with the second most up-votes. All of them seem like they would be good ways to avoid using global state, but I want to know which of these alternatives is the best performance wise. Obviously this depends on the language you are using, but for my particular question I am asking about JavaScript. However, I think that this could apply to other languages like Java.

So, say I have a JavaScript function that calls 10 JavaScript functions in series (e.g. using the Node.JS async library in an async.series block, the scoping rules of async making this all the more difficult), and this serial operation requires shared variables to handle the state of the entire operation. This state information is no longer useful after the "parent" function returns. Now, one can avoid some of the need for a shared state by practicing good design while writing the functions, but in my specific case I've determined that they all need to read and possible modify the shared state.

So, I can follow mikera's approach and: Instantiate a new function every time this "parent" function is called using a functor to create a closure, for example:

function newFirstStep(sharedState)
{
    return function firstStep(a,b)
    { 
         //some logic with shared state
    }
}

function parentFunction()
{
    var sharedState = {"functionStartTime": 1400232233};
    var step1 = newFirstStep(sharedState);
    step1(1, 2);
}

or define the functions inside the parent function:

function parentFunction()
{
    var sharedState = {"functionStartTime": 1400232233};
    function step1(a,b)
    {
        //logic with shared state
    }
    step1(1,2);
}

The second option screams "bad for code re-use" to me, as well as making it difficult to test step1.

The other alternative is to add an extra context object that I pass into each function call as another argument. When I was trying to figure out how to do this before, I thought it to be extremely clunky and ugly to have to add an extra argument for each shared state variable to every single function just to have the same state, but having just a single context object per mikera's suggestion means I only have to add one extra argument to each function. This is much more palatable. However, it just "feels" unnecessary to have to pass this around since all of them "share" it. Perhaps I am just way too obsessed over an extremely minor detail?

Anyway, so here is my question: If I use either of the possible ways to create a closure (functor or define directly in the parent function), it seems extremely inefficient to have to create 10 brand new functions every time I call this parent function. I mean, 95% of the functions are already defined. This just seems really inefficient... and I would feel the same way about doing that in a language like Java (creating new instances of objects all the time just to get a shared state).

So, is the context argument the best performance wise? I'm tearing my hair out trying to decide on whether or not to use functors for each function or adding an extra context object argument to each function signature because none really seem like a "great" solution. Am I focusing on micro-micro-optimizations and just need to focus on writing the **** code?

  • thanks for the edit.. I spend a couple minutes making sure all the indents were correct only to find out it was ignored! I forgot there were [code] blocks.. – JavaNovice14085 Sep 24 '14 at 3:14
6

Just write code. Don't worry about performance unless performance is shown to be a problem.

And to the two you have, let me add a third. Create a base object with all of the desired functions as methods, expecting this to have your state. Then have your stateful objects set the base object as their prototype. And now your methods simply exist, and get called, and state is passed around without having another visible parameter.

I am not a JavaScript programmer, and so don't have a strong opinion about which of these is best.

  • 1
    I can't up-vote this also, but this is a great answer. Just to provide me with some concrete numbers, I ended up writing 4 test files, one for each approach: Context arguments Functors Closures Prototypes and plan to run each of them a large number of times while a V8 profiler is watching them. I have a feeling that unless the functions are very large (which is bad design anyway!) or a large number of them are created (100s per call) that the performance difference will be minimal. I think that from a readability and code re-use perspective that the prototype or context method are best. – JavaNovice14085 Sep 24 '14 at 11:41
  • I'll try to remember and let you know how it turns out! – JavaNovice14085 Sep 24 '14 at 11:41

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.