views:

88

answers:

4

What would be the best way to abstract away any given JavaScript framework (jQuery, MooTools etc.), that sits on the bottom of the framework stack? Essentially, I would like to have a situation where I could swap out the library, do changes only to one layer of the framework (not to every module, for example), and the whole thing could be up and running again.

So, every module should call a framework function(s), which would then be routed to the library.

+6  A: 

This would be writing a library for...libraries, if you are concerned about performance at all (and why wouldn't you be?) you should go a different route altogether. Another abstraction layer on top of libraries with very different approaches (especially when you get into utilities, animations, etc.) would be very, very inefficient and time consuming.

No kidding, it'd take you less time to port your code several times even in any decent size project before building (or more importantly, maintaining) a library abstraction layer like this would.

Nick Craver
@nick, there's a profound difference between toolkits/libraries and frameworks. Frameworks are build on top of toolkits and libraries. jQuery and Prototype are nothing more then toolkits, Dojo, Yui and are nearly frameworks and ExtJS can definatly be called a framework.
BGerrissen
@BGerrissen - It depends on your definition I suppose, with jQuery + jQuery UI added on, how do you call that a toolkit and YUI a framework? I think that's a grey area at best, it's really a question of core vs plugins and where the weight is IMO.
Nick Craver
I am indeed, concerned about the performance, since most of this will be run in mobile devices. However, I am thiking of caching the hell out of the library requests, so that the framework could have direct references to the functions within the library, so that the request doesn't have to travel every time, through every layer.
crappish
@nick, No actually it's not a grey area... It's pretty well defined in software architecture world. View http://developer.yahoo.com/yui/theater/video.php?v=zakas-architecture of Nicholas C. Zakas, specially catered for JS devs..
BGerrissen
+ the problem with porting is that you lose possibility to quickly and/or easily test out different libraries. Currently we are using Mootools, and we already have over 60 calls to library itself. And this is just a barebones prototype. Thus, when we start racking up modules, I would like them to be library independent, so that we don't end up into porting hell, when/if the time comes. Specially, as we would like to be as agile as possible.
crappish
@BGerrissen The framework in question is actually based on Nic Zakas's slides. :)
crappish
@crappish - Do you plan to change frameworks often? :) I just don't see that situation arise much at all, and with mobile I think you'd be concerned with caching, number of requests and overall CPU used, which *will* be greater with another layer on top.
Nick Craver
@BGerrissen - I'm curious as to how you define jQuery UI in toolkit vs framework? It's all JavaScript, and various components (that depend on the core libraries respectively) can be written in the same component ways...which goes back to my point, it's where the weight is. If you can do *everything* that YUI does in a plugin, widget, etc, isn't it just a question of where the weight lies?
Nick Craver
Yes, those (caching and requests) are concerns but there are already solutions in place for those. :) Overall CPU usage is a concern, specially for slower devices, but I am willing to sacrifice a small percentage of speed, if it gives me greater flexibility with the libraries. And yes, we have already tested out few libraries, all of which have bloat on top of them (IE6 for example, which is not a problem in mobile environment). The "bolt-on" library feature would allow us to easily benchmark different solutions and libraries, and even build somewhat custom framework.
crappish
@nick, watch the vid ;) Nicholas explains it better than I can.
BGerrissen
+6  A: 

You may want to use something like the Adapter Pattern. Create your own interface, exposing the methods that you will be using in your application, and then create an adapter for each toolkit that you would like to support (jQuery, MooTools, YUI, etc). Your own interface would then route the method calls to the specific adapters.

If you were to support a new toolkit, all you'd have to do is to write a new adapter that translates methods from your own interface, to the methods of the specific toolkit.

This is something that Ext JS currently does. You can choose which adapter to use (jQuery, YUI, etc) behind the method calls of the framework. For example: Ext.getCmp() would use the jQuery.$() when using the jQuery adapter. However, it is often not a very easy one-to-one mapping.

Ext JS started its life as an extension to the Yahoo UI javascript library. At that time, Ext relied on YUI for all of its low-level cross-browser code. Now that Ext is a standalone JavaScript library, you have the choice of substituting YUI for other JavaScript libraries such as Prototype, or jQuery. The source files that map the low-level Ext API around other JavaScript libraries (or Ext's own base library) are known as adapters and they live in the source/adapter subdirectory. When you include Ext in your website you choose which adapter you want to use.

From: Ext JS Manual: Source Overview

Daniel Vassallo
How would this work really though? Given that the frameworks have a different set of methods and abilities, how would you write one all-encompassing super set of methods? It seems like you'd have to fill in the gaps, every feature that one library has that another doesn't...you'd have to add the functionality where it's missing.
Nick Craver
@Nick: Yes, you're right. I'm not saying it's easy... It's what ExtJS does however. It requires that you choose an adapter. Originally it supported YUI, jQuery, Prototype IIRC, but then they also implemented their own adapter. The good thing is that if you were using their own adapter, but then you'd want to use something that depends on jQuery, you could just switch the adapter. Very neat, but definitely not easy to implement.
Daniel Vassallo
+1 Daniel simply beat me to it ;)
BGerrissen
@Daniel - That's my main point..it's not easy, and *how* "not easy" is a major factor here, I can't imagine it being less work than porting your code when needed. Another reason to *really* stay away from this is the OP is targeting mobile devices with slower processors and connections, making this extra layer that much less attractive. Heavier, more processor intensive and probably more work than porting in the first place...I stand by my strong recommendation to stay away from this altogether, *especially* for this particular application.
Nick Craver
@Nick: I fully agree. My answer was just an attempt to answer the question, especially since I could relate to how Ext JS have tackled it. However, while I could see some advantages in Ext's case, this does not apply for the vast majority of applications. One major drawback, apart for the added complexity, is that you would not be able to exploit particular features of one toolkit, if the same feature is not offered by the others.
Daniel Vassallo
Just to share my experiences. Direct call to mootools getElement ($) vs. sandbox->adapter->mootools resulted to, on average, from 0.40ms vs. 0.95ms (tested with worst case scenario; low end Nokia device, whereas Android devices doesn't really seem to care about the implementation). Even though the execution time increase in percentages was quite high, when you look at the numbers by themselves, we are still under one millisecond per call, which is minuscule compared to the fact that the framework is now library agnostic.
crappish
+2  A: 

This may have been a reasonable idea if the frameworks had equivalent functionality. Unfortunately they don't; they do different things, and they do them differently. There is cross-over between them, but your wrapper would miss out on a lot because you'd only be able to do your wrapping on stuff that was in both. You'd end up with the lowest common denominator; the worst of both worlds.

My advice is to take the time to learn both libraries - MooTools and JQuery are both very good libraries, and it's good to know them both. Even if you then only use one of them in your project, you will at least be able to make an informed choice before you start.

Spudley
+2  A: 

You will have to write adapters for each toolkit/library you might want to use for your framework, pretty much like ExtJS/Sencha has done (though theirs are probably not reusable).

Start out by mapping out what methods your adapter should have, it will act as your frameworks low level API.

Next step is to write an adapter for each possible toolkit/library. Some libraries will be hard to write adapters for like YUI, since they load code dynamically. You might have to compile a single .js file with needed functionality first.

Add a new toolkit/library, write a new adapter according to your mapping.

BGerrissen