When I first learned javascript, I mainly used the jQuery library for small interactions (select something/do something) and adding very basic behavior to the websites I worked on. At the time, it was no big deal to just throw all of my simple jQuery methods and functions in a .js file and be done with it. Today, most of the web projects I work on tend to have significantly more complex behavior than just "select something/do something", utilizing multiple libraries (Kendo, Backbone, Underscore, etc.) with multiple developers involved. As I write more and more JavaScript, I'm finding it increasingly important to have some structure in your code for a couple of reasons:
Recently I've been learning about design patterns to help structure my code and provide some guidance for certain types of complex solutions. If you're not familiar with the concept, design patterns are reusable solutions to commonly occurring problems in software design. Most design patterns follow a predefined form and structure, taking advantage of the combined knowledge and experience of many developers that came before us. Addy Osmani, a Developer at Google, has written an excellent book on the subject called Learning Javascript Design Patterns available free online. The book contains much about the history of Javascript Design patterns with code examples and pros/cons of using each in different types of projects. The most basic and essential pattern for anyone new to to the subject is the Module pattern, which I've been using on most of my projects recently.
The basic concept behind the Module pattern is to help keep individual units of code organized and separated. The pattern is based on the object literal notation, using a self-contained function (providing encapsulation for your code) that returns an object (providing a public API). This is a really important design pattern, since one of the "bad parts" about JavaScript is that all objects & variables not encapsulated are placed in the global namespace, making them vulnerable to other parts of your code. The module pattern encapsulates variables, functions, and states using closures, shielding your module logic from the outside world. This keeps everything in the closure private, while returning public variables and functions for interacting with the module from other parts of your code. Below is an example template of the basic Module pattern:
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
<)();
In the example above, we define a namespace for the module, private variables and methods (created via function-level scoping, ie. closure) as well as public variables and methods being returned as an object. The private variables and methods are completely shielded from the global scope, while still accessible through the public methods. Public methods are namespaced and can be called using dot notation as follows:
myNamespace.myPublicFunction('yo');
A variant of this pattern that I've also been playing around with is the Revealing Module pattern.
This pattern is essentially the same as the Module Pattern above, except all of the functions and variables are defined in the private scope, and we return an object with pointers to the private functionality that we wish to make public.
var myRevealingModule = function () {
var privateCounter = 0;
function privateFunction() {
privateCounter++;
}
function publicFunction() {
publicIncrement();
}
function publicIncrement() {
privateFunction();
}
function publicGetCount(){
return privateCounter;
}
// Reveal public pointers to
// private functions and properties
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetCount
};
<();
The main advantage to this approach is organization and readability. With this approach, we can also define a more specific naming scheme for the module for public methods.
myRevealingModule.start();
Learning these design patterns has helped significantly in my understanding and implementation of coding standards and best practices. It has also made writing JavaScript a lot more fun, because it allows me to think about problem solving more creatively and promotes code re-use.
If you have any experience with learning about design patterns, specifically related to JavaScript, I'd love to hear about it.
Resources:
Comment
Nice post Mike. An firm understanding of design patterns (and anti-patterns) is one of the key things we look for in developers. In addition to enabling best-practice approaches to common tasks they provide a very precise language for developers to use when discussing software architecture.
Interestingly, the modules pattern you mentioned may become a language level concept in ECMAScript Harmony (the basis for the next version of Javascript.) They are similar in many ways to Java packages and C# namespaces. The new syntax makes it easy to manage everything in modules, which is enormously helpful with larger projects involving many developers. Here are some simple module examples.
Here is a nice one page summary of the proposed language features for ECMAScript Harmony.
Hey Mike,
Awesome that you are looking into design patterns!
Dustin Diaz (former googler) also wrote a book on JS design patterns which might be of interest.
http://www.amazon.com/Pro-JavaScript-Design-Patterns-Object-Oriente...
Shichuan also has a good archive of patterns although some of these are more oriented around best practices.
http://shichuan.github.com/javascript-patterns/
Best,
Scott
Great post. It's super easy to write a few functions in your $(document).ready and call it a day. Wrapping it in a module also gives you something to test.
© 2024 Created by Daniel Leuck. Powered by
You need to be a member of TechHui to add comments!
Join TechHui