The best part of
learning a new programming language is the bag of surprises that await you at every line of your program. And it's almost always a mixed bag - things that you were confident of, often do not work the way all the blogs have claimed to be. Your favorite idiom that you have so long used in every design starts falling apart. And you start
thinking in a new way, in terms of the language which you have started learning. Sometimes you feel bad when your favorite design pattern finds no place in the laws of the new land, but soon you realize that there is a more idiomatic way of doing the same thing.
I have been a passionate Java programmer for the last eight years and started the journey with the same sinking feeling coming from the land of C and C++. I missed the sleak idioms of memory management using smart pointers, the black magic of template metaprogramming and a host of other techniques and patterns as evangelized by the language called C++. Now when I learn new
idioms from languages like Javascript and Ruby, I always try to think how it can be mapped to an equivalent construct in Java. Not that there is always a mapping between the dynamically typed world of Ruby or Javascript and the land of static typing that Java implements. Still it's always an enlightening exercise trying to emulate the best practices of one language in the other.
This post is about one such recent experience with programming in Javascript. I was trying to get some stuff from the front end - I had to write an abstraction which will do some computation based on those values. Some parts of the computation had a fixed algorithm, while some parts varied depending upon the environment and context.
Strategy ! I thought .. this was my first reaction to the solution. Since I am not using a statically typed language as Java, I need not implement the delegation-backed-by-the-polymorphic-hierarchy-of-strategy-classes idiom. And I knew that Javascript supports
closures as a higher level of abstraction, which I can use to model the pluggability that the variable part of the abstraction demands. Depending upon the context, a different closure will be passed, and I could make the variable component a closure and pass it along into the main computation routine. But the problem comes up when you have multiple such variabilities to model in the same abstraction. For every such variable point, you need to pass a closure as an argument.
function WageCalculation(taxCalculator, allowanceCalculator, ...) {
}
Works, but may not be the best way to model in Javascript. After some more digging, I came across the details of the Execution Context in Javascript. All Javascript code gets executed in an execution context and all identifiers are resolved based on the scope chain and an activation object. And Javascript offers a keyword
this
, which gets assigned as part of the process for setting up of execution context. The value assigned to
this
refers to an object, whose properties become visible to accessors prefixed with the
this
keyword in the main function. Hence all variabilities of the abstraction can be made part of this context and made available to the main computation routine through the
this
keyword. And this is exactly what
Function.call()
and
Function.apply()
do for us!
Simplifying my example to some extent for brevity, let us say that we are trying to abstract a routine for computing the wages of employees. The wage calculation contains a few components, the basic wage, the tax and allowance. Of these, the percentage of tax varies depending upon the category of the employee, while the other components follow a fixed algorithm. For simplicity, I assume hard coded values for each of them, but applying the variation where necessary.
The basic abstraction looks like the following :
WageCalc = function() {
this.taxCalc = function() {
return 0.2;
};
allowanceCalc = function() {
return 0.5;
};
this.wage = function(basic) {
return basic - this.taxCalc() * basic + allowanceCalc() * basic;
}
};
and I invoke the calculation method as :
var w = new WageCalc();
print(w.wage(1000));
for a basic wage of $1000. The tax calculation component (
taxCalc()
) is a variable part and has been tagged with the
this
keyword. This is the candidate that I need to implement as a strategy and plug in different implementations depending on the context. If I want to have another implementation where the tax percentage is 30, instead of 20, I just do the following ..
MyWageCalc = function() {
this.taxCalc = function() {
return 0.3;
};
};
and invoke the wage calculation function, passing in the new function object as the context. This is what the
apply
method of Javascript
Function
does :
var w = new WageCalc();
print(w.wage.apply(new MyWageCalc(), [5000]));
Here
new MyWageCalc()
sets up the new context on which the
this.taxCalc()
of
wage()
method operates. Hence the new tax calculation functions with 30% of the basic and not the 20% as defined in
WageCalc()
function.
I have only started to
learn Javascript, hence I am not sure if this is the most idiomatic way of solving the problem at hand. But to me it appears to be exciting enough to share in an entire blog post.