News

Sane Namespacing and Object-Oriented Development with Javascript

Written by UI-Staff

Sane Namespacing and Object-Oriented Development with Javascript

I've always had a love-hate relationship with JavaScript. On one hand, JavaScript will let you easily implement any multitude of sins – similar to languages like Ruby, Python, etc. On the other hand, you can also pull of some pretty neat tricks with an expressive language like JavaScript. As the level of interactivity that people expect from the web continues to increase, much of the logic that used to run on the server side has transitioned to the client side – e.g. executed in the browser via JavaScript. Usability features like auto-complete, date pickers, accordians, etc., can be easily accomplished with JavaScript and libraries like Jquery or MooTools.

Naturally, as we continue to see more and more logic moving from server side to the browser, there comes a greater need for code organization when we build projects and applications with JavaScript. One method for code organization in traditional software applications written in Java and C++ is the concept of a namespace: an abstract container which provides context for the code we write. Using namespaces, we can logically organize objects and classes like "TelevisionShows.Children.MyLittlePony()" instead of using extremely long names like "MyPackage_MyClass_SomeFunction()".

Aside from saving keystrokes, we also see benefits when we work with other developers. Take for instance the situation where two developers are working on the same project and define a class named "Location". Both of these developers are unaware that the other is using the same name for a class. To further complicate the matter, developer #1's Location class is used to define latitude/longitude information, while developer #2's Location class is used to define street address, city, and zip data. When the two developers combine their code into the final project, chaos will ensue as the interpreter or compiler will not know which definition of Location to use. This is called a namespace collision and happens frequently when developers are working on problems with similar language semantics or abstractions.

Here's how we fix it in a language like Java:

// File 1: import com.urbaninfluence.GeoLocate.Location;

Location myLoc1 = new Location(); // refers to GeoLocate.Location

// File 2: import com.urbaninfluence.Models.Store.Location;

Location myLoc2 = new Location(); // refers to Models.Store.Location

Now, when the two developers combine their project code, the namespace collision is avoided and no one has to flip a coin to see who has to refactor their code. Namespacing is a concept that's been proven to work well in many modern programming languages, so why don't we use the same concept in a language like JavaScript? Well, because it's kind of a pain in the ass to be honest. Next I'll show you how we use namespaces in our JavaScript development to improve code organization, reduce the chances of namespace collisions, and make it easier for developers to abstract ideas into sensible packages.

Low-fuss Namespacing

I should note that the following example is a front-end JS library which provides functionality for a mall store directory. In total, the file is around 600 lines of code, so organization is an important aspect of keeping the source code manageable. Let's take a look at the first 40 lines of code from one our recent JavaScript applications and discuss:

myproject-header

By including this structure at the top of our JS file, we've essentially provided table of contents for all the different objects that live in this file. Similar to header files in C-based languages, the user of this library can quickly get a grasp of both the functionality and data structures used below just by looking at the first lines of code. This has the benefit of reducing overall complexity of the file and also provides an example of self-documenting code. It also allows us a central location to define static information (similar to constants in other languages) which are used repeatedly throughout the application. I've come to use this standard in JS development as it helps make large chunks of source code easier to manage.

So what does the implementation of one of our objects look like using this approach? Let's look at one the object defined in our file, MyProject.DirectorySearch.AlphaRangeSearch. This object allows the library user to perform an AJAX search looking for stores whose names begin with a character rangeStart through rangeEnd. For instance, searching for all stores whose name begins with an 'A' all the way through 'Z':

Directory Search module

In the above example we see a simple constructor along with two instance methods we are adding to the object. As you may have guessed, each of our search classes implements a run() method which performs tasks unique to each search method and returns a result to a callback function. In addition to reducing the chance of naming collisions, this technique provides an invaluable form of organization that really helps when our source files start increasing in complexity.

One downside to this approach, however, is the extra verbosity needed when referencing objects in our MyProject namespace. Like all things development, the usefulness of this approach really depends on the context in which it's used and how complex your objects are. If you need to whip out some simple JQuery for a modal pop-up window this approach can be heavy-handed, but in larger projects it can help us write self-documenting source code that's easier to understand and manage.

How do you tackle source code management with JavaScript? If you have some JS development tricks you'd like to share, let us know!