You may have come across some scripts out in the wild that have different versions available for a few libraries and wondered how it’s done – surely the author didn’t write the same script 5 times, how on Earth would he remember to roll out the bug fixes across all the versions? You may also have had to create a script that your client will redistribute to other websites; you don’t know what library the website will use, if anyway. You will have to hand your script over to that website’s developer and he will not want to go through your application decoupling it from your preferred library, he will have his own preference that may not match yours or he may have to use the company’s own (that’s how BBC Glow and YUI started).
In technical terms, you create a series of mixins and call them with the objects as the context (because Angus Croll’s idea was really cool), the mixins contain the interaction with library. So long as the mixin retains the same methods (although more may be added if it makes interaction easier), the interface is preserved and the implementation doesn’t matter. If the objects never interact with the library directly, the library itself becomes modular through the mixins.
To better explain that previous paragraph, let’s build a jQuery image viewer using this mentality. To start with, here’s an example of the image viewer tightly coupled to jQuery. While it’s a far better idea to build the objects with an abstracted library in mind rather than taking an existing object and slowly abstract the library out, this order does make demonstration easier.
Now we start building the mixins. The mixins will be the only part of the application that directly uses the library, everything else will interact with the mixins. I’ve find it easier to think of the mixins controlling a small part of the library: classes, DOM tree traversal, animation and so on. Here’s the same example with the classes abstracted out and the “show” and “hide” methods re-written to take that into account. You may have noticed that I use the “jQuery” variable inside the mixins rather than the dollar sign; this simply helps me identify the library being used at a glance, it’s not essential.
You may have noticed the leading capital on the mixin name. This is because of a side effect of Croll’s idea (and one that he didn’t mention at the time) is the ability to execute the mixin and create a new instance of it. I’ve found this to be a remarkably handy trick when it comes to DOM tree traversal and especially for events. Here’s the same example with the traversal abstracted. As you may have noticed, we’ve had to do a little more work in the “draw” method so that we’re only passing DOM nodes to the mixin. Also notice inside the DOM ready function we now use the mixin to find the elements rather than jQuery itself.
Finally, take a critical look at your library usage. There are some instances where creating a mixin isn’t worth the hassle. A perfect example is jQuery’s createElement wrapper: when creating a simple element, document.createElement will do the same job and without the overhead of a wrapper. This can be the same for simple appending and removing of nodes, although I have found that the amount of time necessary to create my own version of “insertBefore” or “empty” is about the same amount of time necessary to make the mixin, if not more. My next example shows the application without any references to jQuery.
Changing the library
Now that we have an application that’s completely detached from the library, it’s possible to change the library itself without changing the application at all. Best of all, if you need to use a library you’re not familiar with, you simply need to learn how to build the mixins. As you can see in my next example, replacing jQuery with PrototypeJS is fairly straight forward.
Wrapping it up
By abstracting out your library, it’s possible to make it changeable at a later stage. I’ve heard it said that the best thing you can do to make your code robust is to think “I don’t know how this will end up” (I think Nicholas Zakas said that, but I can’t find the link) because you instantly start coding more defensively. If you don’t even know which library you’ll end up using, start here.
By the way, if you like this style of coding you may like my Mixin Micro-library – it takes some of the more repetative tasks that this style of code generates and provides handy functions to do it for you.