My JavaScript book is out!
Don't miss the opportunity to upgrade your beginner or average dev skills.

Saturday, July 12, 2008

An alternative JavaScript development pattern

A common pattern to develop JavaScript libraries is to use different behaviours inside methods, and based on browser, or browser plus its version.For about 80% of cases, these behaviours are Internet Explorer dedicated.This approach is good enough, otherwise we could not have a wide variety of libraries to choose, but is this way to develop libraries the best one?

These are some pro concepts:

libraries could be usually merged into a single file, so we can add only one script tag, and for every browser

libraries maintenance or improvements are focused into one, or more, constructor, function, or method

The expected result is, usually, a method that is capable to understand which browser is running them, and what to do for that specific case.

Is above code clear enough? If a browser implements attachEvent, use them, otherwise if it implements addEventListener, use them, otherwise use manual onload implementation.

If we would like to modify, for some reason, that method, there is only one "place" to do it, the method itself.At the same time, every time we would like to use that method, the browser has to check 1 or 2 times which case is suited for its engine.

This concept introduces these side effects:

every method size is generally increased for every browser, and often only to make some task IE compatible

every method speed execution, is generally increased, because of useless, or necessary, checks to perform each time the method is called

every change inside every method, could cause side effects for other browsers, so we have to fix 3 to 4 times instead of once, because of possible problems

every changed method should be tested into every library supported browser, even if it worked perfectly with every one, IE a part

Lazy, or direct, method assignment

Some library implements lazy prototype assignment, so that method will be the best one, only after the first time we will use them.

Since we could perform that kind of check directly during prototype assignment, in this case, above pattern, is completely useless.On the other hand, doing lazy or direct dedicated assignment, we are using a better approach because:

method is specific for this, or that, browser, so its execution speed will be the fastest possible

if we need to fix that method, we can focus only into specific browser version. Accordingly, we do not need to test with every supported browser, every change we made, but only with one, or more, specific version

Code minifier maniacs, could think that in this way, and for each method that requires that strategy, the final size of the library could increase about 30%, and this is, basically, true.So, at this point, we have the best method ever to perform that specific task, but not the best size. How could we solve this last problem?

An alternative library development pattern

Before I will talk about my proposal, we should focus on a simple, as useful, thing about libraries: modularityWhat we do like about this, or that, library, is the possibility to include only what we need, to obtain the final result with smallest possible footprint.In other words, we chose exactly what we need, and we load or use only them, without useless piece of code that could only increase our page size, with or without cache help.A lot of libraries use this concept runtime, like Dojo, or directly during library generation, like MooTools.This way to develop, mantain, and use libraries, is loads of benefits for both developers, and users.At the same time, and as far as I know, nobody though to port this development pattern, to create each library "portion" a part.This is an example of what I am talking about:

// if we would like to support really old browsers too, in a separated filemyGorgeusLib.prototype.sayHello = function(){ onload = function(onload){return onload ? function(){onload();alert("Hello")} : function(){alert("Hello")} }(self.onload);};

This is a benefits summary, about this proposal:

smallest library size ever, thanks to common standard methods used by the library itself (a sort of FireFox, Opera, and Safari dedicated version)

"future proof", when IE will implement standard DOM or Events methods, and behaviours, we can reduce IE dedicated file size

single debug, modular updates. We changes only one, or more, file, instead of recompile, regenerate, redistribute, the entire library file

intranet friendly, update only library version for dedicated environment, if it uses only a specific browser

So why shoulld we use JavaScript to define library behaviour, instead of browser itself?Anyway, this pattern completely brakes practices about script tags in a generic (x)?HTML page. But, at the same time, could be the key to solve a wide number of problems, starting from modern devices with possible memory limits for JavaScript files, up to library execution speed, the best possible, and maintenance, focused in a single browser, or a single browser version.The best implementation could be a Dojo "progressive library load" style, where the core automatically knows which file should be loaded, depending on browser, or its version.Finally, these are side effects about this pattern:

final and complete library size will be the biggest possible one, but there shouldn't be a case where a browser download every file, redefining N times one or more methods

more effort to develop an entire library using this way, if there are a lot of methods that are not compatible with every browser

probably something else, that I am not thinking about

Now, after this explanation, would you like to write your impressions? Cheers :)

It is probably true, but at the same time, my post talks about a way that will improve libraries speed from 0 to 60%, where 0 are every common functions or prototypes, while 60% are those methods with more if, else if, than clear code, to make the single method portable everywhere :)

I think that it does not make sense to publish your stuff here, since I was talking about a development pattern for FF, Safari, Opera, moving IE away, and your link talks about Windows 98, and your IOC stuff, that is not related :D

andrea, that was only an example but in the end the approach is similar, i only load a function using a configuration file.

if instead of xml you use that library you develop for extend json using function, and using a similar approach you can load function externally using browser recognition (using Conditional comment) and for example using a schema like this

Hmmmm...Andrea, I think you just inspired a new application for my Ajile library!

I hadn't really thought about using it's on-demand loading as a way to late load functionality based on user-agent detection. Ajile's AddImportListener() function can actually be used to late load functionality based on the existence of a specific object like document.all.

I've been doing some work to make that function more generic, as in useful outside the concept of namespaces. That should make exactly what you've described trivial to do...if it isn't already...I haven't tested the current Ajile release specifically for this type of use but it may already be possible to some extent...