A Clinic for premature Initalization (context: JavaScript)

Premature Initialization is the source of all evil. Yes? OK? Fine then. That is bombastic blog statement out of the way. Now let’s dive into some serious JS.

Firs let me be clear: There is hardly anything new in this post. This subject has been presented before.  Still, I see too much of a JavaScript code, these days, where this simple programming idiom, is somehow still not in use. So why not revisit this issue for the sake of new generations.? OK, then let’s start. But, we will not start with initialization but with the modularization. One JavaScript idiom in widespread use. Yes, I am sure anyone will agree that JavaScript closures are in widespread use these days.

 

System Initialization
System Initialization

 

Here is a trivial one:

I hope we do not have to debate here why do we use JS closures to implement kind-of-a-modules, etc. The above is by far the most prevailing pattern for creation of kind-of-a-module using JS. It is based on the definition and immediate calling of the anonymous function. Right?

Well … not exactly “right”. Here is the problem. A lot of very happy JS developers are using this pattern for implementing initialize-once-use-later “clever” mechanism:

Above we have an immediate initialization of the rx. That is because closure is just an anonymous function that is immediately called (executed). So inside the closure, we prepare all the static or constant content we will need for the actual worker function to use when subsequently called. And because all of this initialized and hidden “closure” stuff stays hidden, you have this warm feeling about being clever JavaScript uber geeks, which is always a “good thing”, is it not?

Very quickly this becomes your habit and you happily sprinkle this “awesomeness” all around your “awesome” code. But herein lies your problem, as there are problems with this pattern, overzealous usage.

First of all this pattern if used “all around a place, by everyone” (meaning by “tons” of libraries included)  slows down the loading time of pages where your “awesome” code is loaded too. This is simply because immediately after code gets loaded, there is a lot of JS work happening, which is executed all around your little or large closures. *before* any event has a chance to be dispatched for example. Therefore (and simply) page loading time can be vastly expanded, in presence of a lot of complex initialization code inside a lot of closures. And remember, not just in your code but in numerous jQuery plugins and a such, that you are including in your “awesome”, single page, web app.

Second (big) issue. This mechanism can not be used to reference other parts of the object which it is part of. Quick explanation:

Above might be a good example of a programming resilient to change. But JavaScript will not do it and instead, it will “explain” to you, what is wrong:

Above is because you are immediately executing a closure which is how you thought you will code your ToolBox.is4d() function. So from the closure, you are calling ToolBox.rx. Which is “no-can-do” because ToolBox at that moment in time is not fully made yet. It is simply null.

Third problem. Closure mechanism presents difficulties when referencing the variables or objects external to the closure.

Above code is not “adorned” with error checking, because of usage of assert() on the required type. Clever stuff? Robust coding?

I beg to differ. This code also depends on external library and thus references some external string storage in order to prepare the message for the eventuality it might be needed inside the worker. And yes, in turn this string storage, once was, but then it might or might not be defined when needed for a variety of reasons. It is likely defined in another module not made by you. Or even bought by your company. That js file might be simply not included before this code, by mistake. Or someone somewhere, has decided after some time to quietly insert “modernised” new version? So perhaps MSGID constants are not used any more, etc. If any of these is true, your code will stop at the java script file loading initialization time. Which is the worst time to stop and notoriously difficult to debug. The point I am making here is not that your code is lousy, the point is that it is lousy and it also happens before somebody else can spot it in a normal way. Team work, remember?

What happens now? Your team awesome and complex single page app, is suddenly not loading any more. And your clever and robust contribution might be just a single little module (possibly uglified) in this huge and important page where dozens of other clever and important “uber geeks” and their (also uglified) modules are working. And you have made clever test environment, and yes “just yesterday” this code has passed all clever and difficult unit tests.

But now sirens are starting to wail. Main lights are off, only red emergency dimmed lights are on. Bullet proof shutters are up. Even some light smoke can appear, from somewhere. Alarm siren is by now very loud. Crew is alert but standing still and looking at you. And all eyes are onto you. Are you the alien now? Horror indeed.

Instead of sacking you, your good company has decided to send you to me. To the “Clinic for premature Initialization”. Welcome. Relax.

There is a medicine for you. It is effective and it works. Stop shaking, calm down and think. Source of the evil was that you did initialization prematurely. Yes,yes. As everyone else does and they are not punished (yet). But that is not the point.

Initialization mechanism you have used is not lazy initialization. It simply happens too soon! It is even not an initialization pattern! So … Just say no to closure as initialization pattern. Do not confuse initialization and modularization. Enough of this long patronizing and lets give you the solution and medicine:

Phew! That is a lot of comments for such a little function. Ultimately this implementation pattern, depends on the ability of JavaScript to redefined the function inside its own body. I can not overstate how important this pattern is. It could (and should) be used everywhere in your code where immediate initialization happens. If it has not hurt you yesterday, it will tomorrow. So remove it today. Back to the code. This also is a solution to a second problem we presented.

Closures and Lazy Init Pattern combined

But. “There is no silver bullet” as it is already known. This pattern if used everywhere can lead to a lot of variables and object which GC might (or will) not be able to swipe, thus potentially our lazy initialized uber-clever-code might keep a lot of memory in use.

Here one can use an excellent combination of lazy initialization and standard closures. Here is the problem again. Watch closely.

Above, it is very likely that GC will not know1 that a,b,c,d,e can be swiped. One simply can not be sure. Instead of wondering will it or will it not, just use a standard closure. The key is to encapsulate the closure inside the lazy initialization!

Voila! All of your to-be-temporaries are now temporaries indeed. When the anonymous closure function exits they are all swiped; just the result is preserved.

Conclusion

Examples here are deliberately simple. In order to explain the Lazy Init aka just-in-time mechanism.
It is important to understand the implications when using the “self-igniting” mechanism of the anonymous function closures-as-modules. Use both patterns but know when to use which one. And above all: Do not confuse the two.


1: Although these days modern JS engines do contain some pretty clever GC’s.

3 Replies to “A Clinic for premature Initalization (context: JavaScript)”

  1. Nice article, thanks. I found a small typo:

Comments are closed.