Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Javascript Code Design

Smart-designed Code is much easier to maintain, optimize, and extend. There are three high-level aspects to code design that are particularly important.

- System architecture — the basic layout of the codebase. Rules that govern how various components, such as models, views, and controllers, interact with each other.
- Maintainability — how code can be improved and extended
- Reusability — how reusable are the application’s components and how easily can each implementation of a component be customized

In looser languages, specifically JavaScript, it takes a bit of discipline to write well-designed code. The JavaScript environment is so forgiving that it’s easy to throw bits and pieces everywhere and still have things work. Establishing system architecture early and sticking to it provides constraints to your codebase, ensuring consistency throughout.
One approach consists of a tried-and-true software design pattern, the module pattern, whose extensible structure lends itself to a solid system architecture and a maintainable codebase. It occurs useful modules within a jQuery plugin, which makes for beautiful reusability, provides robust options, and exposes a well-crafted API.

The module pattern

The module pattern is a simple structural foundation that can help keep your code clean and organized. A module is just a standard object literal containing methods and properties, and that simplicity is the best thing about this pattern: even someone unfamiliar with traditional software design patterns would be able to look at the code and instantly understand how it works. In applications that use this pattern, each component gets its own distinct module. For example, to build autocomplete functionality, you’d create a module for the textfield and a module for the results list. These two modules would work together, but the textfield code wouldn’t touch the results list code, and vice versa. That decoupling of components is why the module pattern is great for building solid system architecture. Relationships within the application are well-defined; anything related to the textfield is managed by the textfield module, not strewn throughout the codebase—resulting in clear code. Another benefit of module-based organization is that it is inherently maintainable. Modules can be improved and optimized independently without affecting any other part of the application.

Building a module

Let's define three methods and a property that are used to manage the interactions of the menu system.


var menu = {
    animated: false,
    open: function( ) {
        //…
        this.setStyle( );
    },
    close: function( ) {
        //…
        this.setMenuStyle( );
    },
    setStyle: function( ) { 
		//… 
	}
};

The idea is to break down code into the smallest, most reusable bits possible. We could have written just one toggle() method, but creating distinct open() and close() methods provides more control and reusability within the module. Notice that calls to module methods and properties from within the module itself (such as the calls to setStyle )) are prefixed with the this keyword — that’s how modules access their own members. That’s the basic structure of a module. You can continue to add methods and properties as needed, but it doesn’t get any more complex than that. After the structural foundations are in place, the reusability layer—options and an exposed API—can be built on top.

jQuery plugins

The third aspect of well-designed code is probably the most crucial: reusability. While there are obviously ways to build and implement reusable components in raw JavaScript, it's preferrable to build jQuery plugins for more complex things, for a few reasons. Most importantly, it’s a form of unobtrusive communication. If you used jQuery to build a component, you should make that obvious to those implementing it. Building the component as a jQuery plugin is a great way to say that jQuery is required. In addition, the implementation code will be consistent with the rest of the jQuery-based project code. Before you begin building a jQuery plugin, ensure that the plugin does not conflict with other JavaScript libraries using the $ notation. We can wrap our plugin code like so:


(function($) {
    // jQuery plugin code here
})(jQuery);

Next, we set up our plugin and drop our previously built module code inside. A plugin is just a method defined on the jQuery ($) object.


(function($) {
    $.Menu = function( ) {
        var menu = {
            animated: false,
            open: function( ) {
                //…
                this.setStyle( );
            },
            close: function( ) {
                //…
                this.setStyle( );
            },
            setStyle: function( ) { 
				//… 
			}
        };
    };
})(jQuery);

All it takes to use the plugin is a call to the function you just created.


var menuInstance = $.Menu( );

Options

Options are essential to any truly reusable plugin because they allow for customizations to each implementation. Every project brings with it a set of design styles, interaction types, and content structures. Customizable options help ensure that you can adapt the plugin to fit within those project constraints. It’s best practice to provide good default values for your options. The easiest way to do that is to use jQuery’s $.extend( ) method, which accepts (at least) two arguments. As the first argument of $.extend( ), define an object with all available options and their default values. As the second argument, pass through the passed-in options. This will merge the two objects, overriding the defaults with any passed-in options.


(function($) {
    $.Menu = function(options) {
        var menu = {
            options: $.extend({
                'animated': false,
                'duration': 500,
                'orientation': 'horizontal'
            }, options),
            open: function( ) {
                //…
                this.setStyle( );
            },
            close: function( ) {
                //…
                this.setStyle( );
            },
            setStyle: function( ) { 
				//… 
			}
        };
    };
})(jQuery);

Beyond providing good defaults, options become almost self-documenting—someone can look at the code and see all of the available options immediately.Expose as many options as is feasible. The customization will help in future implementations, and flexibility never hurts.

API>/code>

Options are terrific ways to customize how a plugin works. An API, on the other hand, enables extensions to the plugin’s functionality by exposing methods and properties for the implementation code to take advantage of. While it’s great to expose as much as possible through an API, the outside world shouldn’t have access to all internal methods and properties. Ideally, you should expose only the elements that will be used. In our example, the exposed API should include calls to open and close the menu, but nothing else. The internal setStyle() method runs when the menu opens and closes, but the public doesn’t need access to it. To expose an API, return an object with any desired methods and properties at the end of the plugin code. You can even map returned methods and properties to those within the module code—this is where the beautiful organization of the module pattern really shines.


(function($) {
    $.Menu = function(options) {
        var menu = {
            options: $.extend({
                'animated': false,
                'duration': 500,
                'orientation': 'horizontal'
            }, options),
            open: function( ) {
                //…
                this.setStyle( );
            },
            close: function( ) {
                //…
                this.setStyle( );
            },
            setStyle: function( ) { 
				//… 
			}
        };

        return {
            open: menu.open,
            close: menu.close,
            toggle: function( ) { 
				//… 
			}
        };
    };
})(jQuery);

API methods and properties will be available through the object returned from the plugin initialization.


var menuInstance = $.Menu({
    duration: 1000,
    //…
});
menuInstance.open( );

Blog Categories

  • General
  • Showcase
  • Technical
  • White Papers


This post first appeared on Shield UI Blogs | Shield UI, please read the originial post: here

Share the post

Javascript Code Design

×

Subscribe to Shield Ui Blogs | Shield Ui

Get updates delivered right to your inbox!

Thank you for your subscription

×