Singleton to Prototype Design Guidelines

This is a series of posts that explains some of the fundamental rules for developing complex JavaScript applications.

I am a real bugger when it comes to how my code is organized. Given the advanced user interfaces that we have today I have often noticed that JavaScript developers have become, for lack of a better adjective, bloody lazy!  Before we get into the singleton design patter a short discussion is warranted on when a singleton should be used versus a class that supports instantiation.

The most common examples of a singleton are existing JavaScript frameworks such as ExtJs, jQuery, etc. In essence we would only ever have a single instance of each of these frameworks each represented by its own unique namespace Ext and $ respectively. The other most common example of the singleton pattern is the root namespace that represents your JavaScript application because you would under most circumstances only have one. Note I said most circumstances.  There is often the case in the real world where a requirement initially requires a singleton pattern but over time it becomes evident that a class instance would be better.  The golden rule of ‘the only constant is change’ should always be kept in mind when designing your code structures. The purpose of this post is to demonstrate how to effectively use the singleton pattern properly and in such a way as to allow for the easy migration to a class pattern. The secondary goal is to show how writing your singletons in this fashion leads to consistency of code which is something we should all strive for!

First let’s look at the basic singleton design pattern that I often see exemplified on the web.

var mySingleton = {
                 globalVar1 : null,
                 globalVar2 : null,
                 myMethod1 : function(){},
                 myMethod2 : function(){}
 }

So I will state this very clearly and strongly, the above is NOT a singleton.  In my opinion this is a simple object that does nothing more provide a hierarchical structure of variables and methods under a root namespace.  For starters this pattern does NOT use closures and does not have the concept of private/protected vs public methods and variables. At a minimum the singleton design pattern should be written as follows.

var mySingleton = ( function(){

                 // private/protected variables and methods
                 var myVar1 = null,
                 myVar2 = null,
                 method1 = function(){…}
                 method2 = function()(){…};

                 // public variables and methods
                 return {
                                 publicVar1 : null,
                                 publicVar2 : null,
                                 publicMethod1 : function(){…},
                                 publicMethod2 : function(){…}
                 }
 }());

As we can see the singleton is wrapped in an out closure with an inner function that immediately executes upon load.  Methods and variables that need to be exposed to a consumer are defined within the return statement. So far so good, but nowhere good enough for me. At the beginning of this post I said I was a real bugger about code design.  In my humble opinion with a touch of ego a singleton or for that matter an instantiable class has the following basic namespaces.

In JavaScript terms this would be written as follows:

var mySingleton = (function(){

                 // Container Object for singleton configuration variables 
                 Config = {},

                 // Container object for private/protect methods
                 Private = {},

                 // Container object for shared methods
                 Shared = {},

                 // Container object for public methods
                 Public = {}, 

                 // Initialization actions
                 initialization = function(){}();

                 return Public;
 }());

Not the initialization function that auto executes before the outer singleton is itself executed and returns its result, in this case anything defined within the inner Public namespace. The Config namespace (ns) is for internal properties or variables that are consumed internally by the singleton.  In essence they are protected/private and therefore could exist within the Private ns. I simply prefer to have them at the root of the singleton at the very top for ease is access when trolling through the code. Note that each of the root ns’s are capitalized.  This is because public and private are both reserved words for future use in JavaScript. My choices of the root namespaces are purely personal and of course you could use any you choose such as Protected versus Private.  The primary purpose though is to logically break up your code for readability.  So long as you are consistent in your implementation that is all that matters. Note also that I define a singleton global variable called me to refer to the singleton itself.

You may at this point be questioning the use of the Shared ns but there is an important definition within the object.  Shared methods are those methods that are consumed by both Public and Private methods.  I cannot name the number of times where I have code within Private that needs to be replicated by Public.  Any such code with then go into Shared. The importance of this is for legibility and to reduce code errors during future enhancements to the class. When a developer is asked to modify a Public method on the class and they see that the method points to a Shared method they immediately know that they need to look at how it is called from the Private method.  This helps to reduce noodled code as I like to call it because I hate noodles but love spaghetti! Let’s look at some pseudo code as an example:

var mySingleton = (function(){
                 var Config = {},
                 Private = {
                                 iAmPrivateMethod1 : function(){
                                                 Shared.method1()
                                 }
                 },
                 Shared = {
                                 method1 : function(){…}
                 },
                 Public = {
                                 method1 : function(){
                                                 Shared.method1()
                                 }
                 }, 
                 initialization = function(){}();
                 return Public;
 }());

Not something important in the above Public ns.The method1 function is not a direct pointer to to Shared.method1 and it NEVER should be. Public methods should always have their own distinct closure, as the British would say ‘It’s just good form’. Notice something else though, the readability of the code becomes very apparent to the developer. This is an incredibly important aspect of good code development, ‘do not write code for just yourself’. To assume that the code you are presently writing will never have to be modified by you later on or by another developer is simply pure ignorance.  I write by the motto of what comes around goes around, well hopefully someday it will, but that’s not the point.

Now that we have the basics of a good Singleton pattern done, let’s look at how we can use basically the exact same pattern for a class.

var mySingleton = (function(){
                 var Config = {},
                 Private = {
                                 iAmPrivateMethod1 : function(instance){
                                                 Shared.method1(instance)
                                 }
                 },
                 Shared = {
                                 method1 : function(instance){…}
                 },
                 Public = {
                                 method1 : function(){
                                                 Shared.method1(this)
                                 }
                 }, 
                 initialization = function(){}();

                 var Component = function(config){
                                 // initialization code for instance
                                 Private.iAmPrivateMethod1(this);
                                 return this;
                 };
                 component.prototype.method1 = Public.method1;
                 return Component;
 }());

As you can see from the above code we now return Component which is of course a function that can be called with the new method as in, myinstance = new mySingleton({config}). All that has really changed is what we are returning and the fact that we now pass around this t represent the instance to the Shared and Private methods.  When the Component is instantiated any private methods should be called to define what is required for your component/widget.  The Private methods are only ever called once on instantiation of the instance.  This is where Private becomes much more apparent. Public methods are also prototyped into the component class and point to the subsequent Public methods.

Granted if you had many methods or parameters within the Public ns you would have a lot of prototype lines after your component definition.  In my next post I will demonstrate how to optimize this process with a single call as well as how to create automatic setters and getters for variables you may wish to expose in your class.

Until then, Cheers
Keith

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s