Code Organization

Contact Us or call 1-877-932-8228
Code Organization

Code Organization

Key Concepts

Before we jump into code organization patterns, it's important to understand some concepts that are common to all good code organization patterns.

  • Your code should be divided into units of functionality: modules, services, etc. Avoid the temptation to have all of your code in one huge $(document).ready() block. This concept, loosely, is known as encapsulation.
  • Don't repeat yourself. Identify similarities among pieces of functionality, and use inheritance techniques to avoid repetitive code.
  • Despite jQuery's DOM-centric nature, JavaScript applications are not all about the DOM. Remember that not all pieces of functionality need to, or should, have a DOM representation.
  • Units of functionality should be loosely coupled: a unit of functionality should be able to exist on its own, and communication between units should be handled via a messaging system such as custom events or publish/subscribe. Stay away from direct communication between units of functionality whenever possible.

The concept of loose coupling can be especially troublesome to developers making their first foray into complex applications, so be mindful of this as you're getting started.

Encapsulation

The first step to code organization is separating pieces of your application into distinct pieces; sometimes, even just this effort is sufficient to dramatically improve the reusability and editability of the code.

The Object Literal

An object literal is perhaps the simplest way to encapsulate related code. It doesn't offer any privacy for properties or methods, but it's useful for eliminating anonymous functions from your code, centralizing configuration options, and easing the path to reuse and refactoring.

Code Sample:

jqy-practices/Demos/object-literal.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="ISO-8859-1">
	<title>Using an Object Literal to Encapsulate Functionality</title>
</head>
<body>
<p>Nothing to show here.</p>
<script src="../../jqy-libs/jquery.js"></script> 
<script>
var myFeature = {
	message : 'hello',
	config: { logger : function(x) { window.alert(x); } },
	
	showMsg : function() {
		this.config.logger(this.message);
	},
	
	init : function(config) {
		$.extend(this.config, config);
	},
	
	readConfig : function() {
		$.each(this.config, $.proxy(function(k, v) {
			this.config.logger(k + ': ' + v);
		}, this));
	}
};

console.log(myFeature.message); // logs 'hello'
myFeature.showMsg();            // alerts 'hello'
myFeature.message = 'goodbye';  // replace message
myFeature.init({                // replaces alert with console.log
	logger : console.log
});
myFeature.readConfig();         // logs config object
</script>
</body>
</html>

The myFeature object here behaves a little like a class with static methods. When the object literal is created, it has two properties and three methods. One of the properties, message, is a data value, the other, config, is itself an object containing configuration information.

Object configuration alteration is provided by the init method, which will copy any incoming configuration data into the config object. The utility method readConfig logs the state of the configuration object, and showMsg is the "useful" method, which simply writes the message to the current logger.

In our feature, there are no private elements. If we wanted any, we would wrap the feature definition in a self-executing anonymous function, and define the private elements within that function, but outside of the myFeature object literal. We would then need to store myFeature into a location outside the scope of the anonymous function, such as window.

The Module Pattern

The module pattern overcomes some of the limitations of the object literal, offering privacy for variables and functions while exposing a public API if desired.

Next