I'm trying to implement an application using node.js and other related technologies. Heading from java land polymorphism but natural, but for the classical programmer node works differently.
The application will load new code during run-time provided by the user. In order for the main core to use this code "we" need to agree on some kind of a convention. Knowing how new Node is I wasn't that surprised that I didn't find the answer. The problem is this issue is rather vague in JS too.
Requirements:
Strong decoupling.
loading new code in run-time.
The solution should be applicable so I can share as much code as possible with the browser.
Update:
I did fiddle around with duck-typing, I've also encountered ideas from Clojure in regards to protocol based implementation.
I would appreciate some code in the answer.
JavaScript, just like most other scripting languages (i.e. no compile-time type checking) does polymorphism through duck typing.
If you're from Java-land you're probably looking for Dependency Injection which generally provides uber decoupling. You can probably use google to find a good dependency injection framework for Node, like this one.
Although truthfully you can probably just make a single Javascript/Coffeescript file that does all the wiring and config loading.
Because of the flexibility of Javascript just about every form polymorphism has been implemented (traits, interfaces, inheritance, prototypes). Each have their advantages/disadvantages but almost all are runtime check (if any) and not compile time.
Personally I would probably just use either Coffeescripts inheritance, traits.js or Javascript's builtin prototype chain.
EDIT: However since you're talking about allowing users to extend the system then callbacks and/or custom events are the preferred approach (i.e. higher order functional programming and event-bus). If you're looking for something substantial like a plugin system then loader-js looks rather complete (tip of the hat to #Larry Battle).
I have a legacy application and I have refactored parts of the application into separate backbone.marionette applications. I do not have the time or the budget to refactor the whole thing and I want my code to be easier to manage which made me think of requirejs.
Most of the files are minified and munged together.
Can I use requirejs for this type of hybrid solution where I can work on separate backbone modules and still access the existing javascript?
As someone who just recently started using Require.js on a legacy, Backbone-using codebase, I feel your pain :-) I used a combination of approaches, which I'll list here.
Let's say you have fileA.js and fileB.js, and you want to convert fileB.js to use Require, without changing fileA.js:
Abuse the global space
Require doesn't force you to import every variable through it; even in a Require-ified file, you can still access global variables the same way you would with non-Require-ified code. This means that if fileA creates all of its variables in the global/window namespace (which is very likely if you weren't using Require before), fileB can access them whether or not fileA uses Require.
This wound up being my solution for most of my legacy files; I just left them as is, and put all the new Require-ified stuff below them. That way every global they create is ready and waiting when the Require-ified files need them.
Now, this is great if fileB depends on fileA, but what if it's the reverse? Well, Require also doesn't prevent you from making new global variables, which means that fileB can share anything it wants with fileA, as long as it is willing to put it in the global space.
Duplicate code
Don't get upset; I know how important "DRY" coding practices are. However, for just a few files what I wound up doing was making Require-ified duplicates. This wound up being necessary because I'm using a Handlebars plug-in for Require to do my template compiling, so if I wanted any file to use Handlebars I needed it to be Require-ified.
To combat the normal un-DRY issues, I added comments to the old files effectively saying "don't add anything to this file, the Require-ified version is the 'real' version". My plan is to slowly convert more of the site to Require over time, until I can finally eliminate the original, obsolete file. We have a small shop, so it works for us, but at a larger company this might not fly.
Refactoring
I know, you said you wanted to avoid this, but sometimes a little refactoring can give you a lot of bang for your buck. I personally barely refactored anything at all, but there were just a couple places were a small tweak greatly simplified matters.
Overall I see refactoring as something you do after you switch to Require (to slowly over time bring your non-Require-ified code "in to the fold").
Shims
Chchrist is correct in saying that shims are a good way to solve the "half-way to Require" issues However, I personally didn't use them at all, so I can't really say much about them except "look in to them, they'll probably be helpful".
For example if you write a plugin you could do this $('#myDiv').doAction() instead of doAction($('#myDiv')). and you have to admit, the first one looks more intuitive. Are there any clear drawbacks of this like performance hits?
You won't see any noticeable performance hit from this, but there is one potential drawback: namespacing your code is very valuable, and makes it easier to maintain (as you probably know). Throwing everything into jQuery.fn may not be the best way to do this.
Personally, I shy away from extending jQuery with very specific things (like app-specific logic or something) but whole-heartedly recommend it for general, DOM-level things (.hasAttr() and .scrollHeight() are two I use a lot). The reason is that there are better places to put app-specific logic (in the module in charge of that area of the app, for example).
A simple heuristic: would it be useful to other people if I made this a public extension? Or is this only relevant to this particular project?
That said, there is no concrete problem with doing this in your code. It's more a semantic issue: is that the best place for it?
Write a jQuery plugin so that you do not need to repeat this over and over again.
There are literally minimal performance issue with this, and mindful that this is at client side, it does not attribute to your server resources.
There aren't any performance hits choosing one approach over the other. It's more of a question of, do you need it as a jquery plugin? I create regular functions if it's a utility function and doesn't need to act upon a jquery object. If it does, then it should be a plugin (no need to pass in the jquery object as a parameter, and you can chain)
You seem to be using jQuery as a framework. It is not one.
Please use a client-side MVC style library like backbone/knockout/sammy/eyeballs for seperations of concerns and structure
Please use an AMD loader like curl/requirejs for modularisation of your code.
Coming from Java, I'm wondering if a Java best practice applies to JavaScript.
In Java, there's a separation of interface and implementation, and mixing them up is considered a bad practice. By the same token, it is recommended to hide implementation details of your library from end developers.
For example, log4J is one of the most popular logging libraries out there but it is recommended to write code to the slf4j library or the Commons Logging library that "wraps" log4j. This way, if you choose to switch to another logging framework such as logback, you can do so without changing your code. Another reason is that you, as a user of a logging library, how logging is done is none of your concern, as long as you know what logging does.
So back to JavaScript, most non-trivial web applications have their own custom JavaScript libraries, many of which use open source libraries such as jQuery and dojo. If a custom library depends on, say jQuery, not as an extension, but as implementation, do you see the need to add another layer that wraps jQuery and makes it transparent to the rest of JavaScript code?
For example, if you have the foo library that contains all your custom, front-end logic, you'd introduce the bar library that just wraps jQuery. This way, your foo library would use the bar library for jQuery functions, but it is totally oblivious to jQuery. In theory, you could switch to other libraries such as dojo and google web toolkit without having a big impact on the foo library.
Do you see any practical value in this? Overkill?
Although it makes sense from a theoretical standpoint, in practice I'd say it's overkill. If nothing else for these two reasons:
Anything that adds to the size of
the request (or adds more requests)
is bad - in web world, less is more.
If you're using say jQuery, the
chances of you switching to
something like Mootools is (imho) slim to none. From what I've seen, the top libraries each aim to solve different problems (at least in the case of Mootools and jQuery - see this great doc for more info on that). I'd assume that you'd incur a tremendous amount of headache if you were to try to implement a middleware library that could easily switch between the two.
In my experience and being a Java developer myself, sometimes we tend to take the whole "abstraction" layer pattern too far, I've seen implementations where someone decided to completely abstract a certain framework just for the sake of "flexibility" but it ends up making things more complicated and creating more code to maintain.
Bottom line is you should look at it on a case by case basis, for example you wouldn't try to create an abstraction layer on top of struts, or on top of JPA, just in case you then go to a different framework (which I've rarely seen done).
My suggestion is, regardless of the framework you are using, create objects and components that use the framework internally, they should model your problem and be able to interact between them without the need of any specific framework.
Hope this helps.
There are a lot of good answers here, but one thing I don't see mentioned is feature sets. If you try to write a library to wrap the functionality provided by, say, jQuery, but you want to be able to easily swap out for something like prototype, you have a problem. The jQuery library doesn't provide all the features prototype provides, and prototype doesn't provide all the features jQuery provides. On top of that, they both provide their features in radically different ways (prototype extends base objects -- that's damn near impossible to wrap).
In the end, if you tried to wrap these libraries in some code that adds 'abstraction' to try to make them more flexible, you're going to lose 80% of what the frameworks provided. You'll lose the fancy interfaces they provide (jQuery provides an awesome $('selector') function, prototype extends base objects), and you'll also have to decide if you want to leave out features. If a given feature is not provided by both frameworks, you have to either ditch it or reimplement it for the other framework. This is a big can of worms.
The whole problem stems from the fact that Java is a very inflexible language. A library provides functionality, and that's it. In JavaScript, the language itself is insanely flexible, and lets you do lots of crazy things (like writing a library, and assigning it to the $ variable). The ability to do crazy things lets developers of javascript libraries provide some really creative functionality, but it means you can't just find commonalities in libraries and write an abstraction. I think writing javascript well requires a significant change in perspective for a Java developer.
Someone wise once said "premature optimization is the root of all evil." I believe that applies in this case.
As others have expressed, you don't want to abstract for the sake of flexibility until you have an actual need for the abstraction. Otherwise you end up doing more work than necessary, and introducing unnecessary complexity before it is required. This costs money and actually makes your code more brittle.
Also, if your code is well organized and well tested, you should not be afraid of major changes. Code is always changing, and trying to anticipate and optimize for a change that may or may not come will almost always get you in more trouble than it saves you.
Acknowledgement: I should give credit to Agile programming and my practice and readings on the topic. What I've said comes directly from my understanding of Agile, and I've found it to be an extremely good razor to cut out the extra fat of my work and get lots done. Also none of what I've said is actually JavaScript specific... I'd apply those principles in any language.
There are good arguments calling this development practice - wrapping in order to switch later - into question in any language.
A good quote by Oren Eini, from his writeup on wrapping ORMs:
Trying to encapsulate to make things
easier to work with, great. Trying to
encapsulate so that you can switch
OR/Ms? Won’t work, will be costly and
painful.
This is definitely something that is done in enterprise environments.
Take for example a company that has their own custom javascript framework that is used on all of their projects. Each of the projects decide to use their own framework (jQuery, Dojo, Prototype) to add functionality to the underlying modules of the company framework. Employees that move between projects can now easily do so because their API with working the project's codebase is still the same, even though the underlying implementation could be different for each project. Abstraction is helpful in these situations.
It is overkill. Javascript is not Java and is not in any way related to Java. It is a completely different language that got J-a-v-a in the name for marketing reasons.
If you are concerned with availability of add-on libraries, then choose a framework with a large ecosystem. In an enterprise environment you will be further ahead by standardising on a vanilla off-the-shelf uncustomised web framework that you can upgrade every year or so tracking the rest of the world. And then supplement that with a SMALL in-house add-on library which you will, of course, have to maintain yourself, not to mention training any new programmers that you hire.
Since you are talking about Javascript in the client (web browser) it is more important that you limit the complexity of the things that people do with it. Don't build huge amounts of client side code, and don't make stuff that is so brittle that another programmer can't maintain it. A web framework helps you both keep the linecount down, and keep your own code reasonably simple.
It is not a question of Javascript best practice, because that would be different for server-side JS such as Rhino or node.js.
Adapter pattern is not a common solution in this case. The only example I know to use this pattern is extjs. Javascript projects are usually too small and they aren't worth the effort you would make by creating such an abstraction layer.
The common solution for this problem is that you try to use multiple frameworks together for example with jquery.noConflict.
I've done this before, and can talk a bit about the experience of writing a library/toolkit wrapper.
The plan was to move from Prototype to some other library. Dojo was the first choice, but at the time I wasn't sure whether that's the library to move everything to (and by everything I mean ~5MB of Prototype-happy JS). So coming from a world of clean interfaces, I was set to write one around Prototype and Dojo; an awesome interface that would make switching out from dojo a breeze, if that was in fact necessary.
That was a mistake that cost a lot of time and effort for a few reasons. The first one is that although two libraries can provide the same functionality, (a) their API will almost always be different, and most importantly (b) the way you program with one library will be different.
To demonstrate, let's take something as common as adding a class-name:
// Prototype
$("target").addClassName('highlighted');
// Dojo
dojo.addClass("target", "highlighted");
// jQuery
$("target").addClass("highlighted");
// MooTools
$('target').set('class', 'highlighted');
Pretty straight-forward so far. Let's complicate it a bit:
// Prototype
Element.addClassName('target', 'highlighted selected');
// Dojo
dojo.addClass("target", ["highlighted", "selected"]);
// jQuery
$("target").addClass(function() {
return 'highlighted selected';
});
// MooTools
$("target").set({
"class": "highlighted selected"
});
Now after choosing an interface for your version of the addClass you have two options: (1) code to the lowest common denominator, or (2) implement all of the non-intersecting features of the libraries.
If you go with the 1st -- you'll loose the "personality" / best qualities of each of the library. If you go with #2 -- your addClass' code will be at 4 times larger than the ones provided by any of the libraries, since for example when Dojo is included, you'll have to write the code for the function as the first param (jQuery) and the Object as the first param (MooTools).
Therefore, although it is theoretically possible, it isn't practical, but is a very nice way to understand the intricacies of the libraries out there.
All of my projects include very similar tasks and quite recently I've been thinking I should write a library to handle most of the heavy lifting so I can write short, simple, easy to read code that interacts with the library to get the jobs done. Looking at other frameworks, specifically jQuery & YUI, they work in different ways. jQuery mostly seems to extend & simplify the DOM using a global object/function whereas YUI uses namespaces and modules. I understand that this is because they have different goals as libraries and each have their merits.
Most specifically, I'm looking for answers to the following questions:
Is it best to use namespaces, eg gui.scrollbar.attach(), or a global method such as $(domObj).attachScrollbar()?
Is it best to include individual parts as seperate js files or as a single js file where components are copied/pasted? I know the eBay Shopping API SDK has many .js files in seperate folders, wouldn't this suffer a significant performance hit?
Is there any other advice you would give to someone looking to create a javascript library?
I've marked as community wiki because I didn't want to risk the question being closed - I'm genuinely seeking advice here.
Thanks
EDIT
I should have originally stated that I'm not re-inventing the wheel, I'm looking to simplify many common tasks between Windows Desktop Gadgets, so I don't need the cross-browser compatibility of other libraries and their core functionality doesn't really apply to what I'm doing. I tried to keep the question general and not specifically relating to desktop gadgets, so that this question would be useful for others.
Simple answer to your question: write your library using an existing one.
I have some javascript files written in jQuery just for such purposes.
More specifically,
If you are going for java-style object oriented-ness, go for namespaces. I prefer the jquery way of writing plugins.
If you are writing your own "toolkit", it would be best to copy and paste the dependencies (minified) into your source code. This way
a. you avoid the overhead you mentioned
b. you prevent unnecessary dependencies creeping up externally.
Cheers!
Concerning your first question, the two options are really the same IMO. Instead of a global object like YAHOO or gui, you have a global function like $. In both cases you have a global variable that holds your namespace.
Is there any reason why you can't use one of the many libraries out there already? This seems like a case of reinventing the wheel. These libraries have been around for years and have already tackled many of the issues that you will surely run into when trying to write your own.
In terms of some of your questions:
This is really a matter of preference IMO. As long as you get your functions out of the global namespace that is the major thing. However, this design choice will drive many others down the line.
It is best to include all core functionality in one file and then to chunk the rest into files that are required for a bit of functionality. You want to keep the number of files down, but you also don't want the user to have to download a lot of stuff that they don't need.
Having said all that, I restate that you should look at using one of the libraries already out there unless you have a very good reason not to. Keep in mind that you will need to test in all old browsers as well as any new browsers that come out.
jQuery, YUI, Prototype, Mootools, extJS are a few of the most popular