30 July 2008

Complex assignments

I find my coding style continues to evolve as time goes on. This suggests to me that I am still a long way off getting it right! However, it also gives me the chance to play with new ideas and introduce new concepts to my code.

One new pattern that I seem to now be using more and more is one I call Complex Assignments.

To introduce this, it is useful to look at simple assignment code first. An assignment is simply setting one thing equal to another:

var myVariable = 1;

 

this.myMember = "Some text";

 

this.myMethod = function() {

    ....

}



These are all simple assignments. Sometimes though this is not enough. Sometimes you need to set the value of a variable based on some parameter, eg:

function( myParam ) {

    var myVariable;

    if (myParam === 1) {

        myVariable = "Some text";

    } else {

        myVariable = "Some other text";

    }

}



Now of course this is a trivial example, but you may find yourself needing a more complex set of rules. In that case, the logic around this assignment can become complex. To alleviate this problem we will often delegate the assignment logic into a function. This is perfectly acceptable and actually desirable and in a JavaScript object we can make a private function to do the work:

function myObject() {

    this.someValue = getSomeValue();

 

    function getSomeValue() {

        //do some work

        .....

        return someValue;

    }

}



However, if this function is only going to get called once, there is no need to make it a named function. In fact I find it neater to make it an anonymous function. Of course, if its an anonymous function that only gets run once, we can make it a self invoking function. To rewrite the example above:

function myObject() {

    this.someValue = (function() {

        //do some work

        .....

        return someValue;

    })();

}



In this instance, the code looks very similar (if somewhat neater). But, with this anonymous self invoked function, we are actually creating another level of scope which will get destroyed once the function has been executed. This can be very useful and can be very efficient. I also think the code is simple to understand and even better encapsulated.

This is particularly useful for the setting of constant like variables. I find myself using this pattern more and more as I find more occasions where I want a function to be used to assign a value to a variable.

4 comments:

Adam Silver said...

Yep, lovely way of doing it. Since I first saw you do it, I have been implementing that in my scripts.

Neil Mosafi said...

It's nice - this is basically an implementation of the Composed Method Pattern. I have to disagree though as I personally think the anonymous function makes things much less readible than if you put the actual work in a named function (even if that function is never reused). This is because you never need to read the other function - it's all in the name!

I would much rather see this.someValue = getSomeValue(), especially when there are several of these calls being done sequentially in a single method

James Norton said...

I do completely understand what you are saying, however, this pattern is more flexible. It can be used in many different situations including those where unarguably a named function would detract from readability - such as assigning a function to an object prototype.

This pattern is also extremely useful in avoiding closure issues within loops where you create a closure around the counter - more on this in a future post.

Edward Spencer said...

That's true about the closure issue. I do think the code looks a little 'messier', though that's purely syntax... all those brackets everywhere. The actual concepts are as clean if not cleaner I think.

One point about the encapsulation though - you say it is more encapsulated but surely it is precisely as encapsulated as before? You still can't access the function from outside so how is it any different?

@neil I do tend to agree, it's human (for me anyway) to want to read the whole function if I see it defined this way - something I wouldn't do otherwise. That's probably more a comment about my brain than about how the code ought to be styled though!

Great blog - just found it as recommended to me by Google Reader :)