javascript: Umbrella pattern
By Anatoly Mironov
There are two great patterns for organizing javascript code: Prototype and Module pattern. More about them later in this post. But in reality I still see much of spagghetti Just an example: SharePoint 101 code samples. They are indeed very simple and isolated examples. And many projects use this simple way in mind when they begin. But when javascript code grows, it becomes a monster. Have you seen this biest? How is this monster created? Through good intentions (like everything else) in form of KISS mantra, to little time and the “commit and run”-behavior, or the worst: “I am c#-er, not Front-End-Developer”-spirit. In this post I’ll introduce a kind of compromise the Umbrella pattern. But before that, let’s see how to recognize the spagghetti monster in javascript:
- All are children of window. All global functions and variables are written directly, not encapsulated in some form. In the web browser all this stuff is appended to window. Variables like “index”, “query”, “selectedItem”, “onSuccess”, “onFail” are especially dangerous.
- Conflicts arise between different functions with the same name. In javascript only the name matters. Eventhough parameters differ, they will be treated as the same function (where the last mentioned will override the previous functions). Try to add Gantt scheme view of a calendar webpart in SharePoint and a simple calendar webpart on the same page. One of them will stop working. Because both use moveToDate with different signatures and which do very diferrent things.
- To avoid conflicts people create camel and Pascal monsters in the function names. Try to pronounce this: getTasksFromCurrentSiteTaskListWhichAreNotFinishedAndHaveBeenModifiedTheLastMonthForCurrentUserForTheProjectNewWave. Have you seen such function names. Leave some funny ones in comments :)
Now from negative to positive.
Umbrella pattern
The umbrella pattern is just a step from spagghetti towards better organization of javascript. So let’s take the spagghetti code and put it underneath namespaces, or call it umbrellas. It will protect from conflicts, give developers a better overview and traceability.
A little example from an imaginary company Takana:
//ensure that you don't override the main Umbrella (namespace)
var Takana = window.Takana || {};
//ensure that you don't override the sub-Umbrella Tasks
Takana.Tasks = Takana.Tasks || {};
Takana.Tasks.get = function() {
//run SPServices, CSOM or jQuery ajax and listdata.svc
};
Takana.Tasks.show = function(tasks) {
//use jQuery.tml, knockout.js, or just jQuery.each to render
};
Takana.Tasks.onSuccess = function(data) {
//e.g.
Takana.Tasks.show(data.d.results);
};
Takana.Tasks.onFail = function(xhr) {
SP.UI.Notify.addNotification("oops")
};
```It reminds most the module pattern, but gives a simpler way to create a module, and, I think, even simpler to refactor. If you need another umbrella, just feel free to create it, e.g. Takana.Notifications. Some other stuff which is not a business module can be shared like Takana.Utils umbrella. The umbrella pattern gives you a better control of javascript, intellisense in Visual Studio and consoles in Firebug and Chrome Dev Tools. By the way. Do you want to know the contents of an umbrella? Just type Takana.Tasks in Chrome Dev Tools and see everything we have there: [![](https://sharepointkunskap.files.wordpress.com/2012/03/umbrella-001.png "umbrella-001")](https://sharepointkunskap.files.wordpress.com/2012/03/umbrella-001.png)
##### Prototype and Module
Let's recap these two patterns. They are really great and they have their own usage areas. The [prototype pattern](http://weblogs.asp.net/dwahlin/archive/2011/08/01/techniques-strategies-and-patterns-for-structuring-javascript-code-the-prototype-pattern.aspx) is more or less a workaround for missing the native object oriented programming api. So it is best to use when you have many objects which are very similar. An example from a "real life":
var Pizza = function(name, bakeSpecial) { this.name = name; this.bakeSpecial = bakeSpecial; }; Pizza.prototype = { bake: function() { if (this.bakeSpecial) { console.log(“Wow, I’ll bake it in a special way”); this.bakeSpecial(); } else { console.log(“Bake. No problem. I’ll do it”); } } }
Now we can create a collection of pizzas:
var pizzas = [ new Pizza(“Margarita”), new Pizza(“Quattro Staggione”), new Pizza(“La Maffia”, function() { // bake in 12 mins instead and keep looking at left and right })]
Did you notice the flexible passing of a special bake instructions for "La Maffia"? Maybe like this one: [![By UggBoy♥UggGirl [ PHOTO // WORLD // TRAVEL ] (CC)](http://farm6.staticflickr.com/5129/5287980888_74997536e7_z.jpg "[ Feeling in the Mood : Pizza Dreams ] London, England, United Kingdom")](http://www.flickr.com/photos/uggboy/5287980888/) Great. Now it is time for Module. The [module pattern](/2011/12/17/javascript-module-pattern/) is a way to encapsulate, a way to simulate private and public "methods". To keep our Pizza example, let's create the Pizzeria:
var Pizzeria = function() {}();
var Pizzeria = function() { //private “methods” var mixIngredients = function() { console.log(“I am mixing ingredients”); }; var makeDough = function() { console.log(“I am making the dough”); }; var giveToEat = function() { console.log(“Ay, ay, hot, here is your pizza”); }
//the object which will be instatiated var pizzeria = { //public “methods” makePizza: function(pizza){ console.log(“I’ll fix your pizza: " + pizza.name); mixIngredients(); makeDough(); pizza.bake(); giveToEat(); } }; return pizzeria; }();
var pizza = new Pizza(“Hawaii”); Pizzeria.makePizza(pizza);
[![](https://sharepointkunskap.files.wordpress.com/2012/03/module-pattern-001.png "module-pattern-001")](https://sharepointkunskap.files.wordpress.com/2012/03/module-pattern-001.png)