Wednesday, March 7, 2012

Best Practices - JavaScript Programming Part 1


Best Practices -
JavaScript Programming 
Part 1


JavaScript is one of the most popular programming languages today. It is widely used by web developers and client side programmers all over the world. But here’s the thing, while technology companies are strict about their server side code to be structured and readable, the client side code does not get the same attention. Often, the web programming is being delegated to 3rd parties or to server developers who are inexperienced with client development. This can lead to a poorly written client which is OK if it’s a throwaway, but what if the code is there to stay and change over time?
This post is for developers who are familiar with JavaScript but want to get a little bit better at it.  All of the tips given hereby are from my own personal experience, they are not scientific facts and should not be accepted as such.



General Styling

A good place to start is the general appearance of the code. If you’re going to take anything from this post, let it be this: MAKE YOUR CODE READABLE!!! There’s no greater hell than trying to understand a sloppily written JavaScript code, especially if it was written by someone else.
Readability can be fairly achieved by following a few basic guidelines:


Use meaningful variable names, even if they get long. For example:

            var divBuilder is better than var db.


Limit the length of your methods, methods should be no longer than 8 – 10 lines.


Newspaper Paradigm:

Let’s observe the following code:

$(document).ready(function ()
{
    ContactPage.RegisterForEvents();
    ContactPage.FillContactInfo();
    ContactPage.FillAdditionalInfo();
});

You’ve never seen this code before but I bet you can guess what it does. This is due to the newspaper like layout of the method, we’re presented with headlines instead of overwhelming details that are kept out of sight at this level. This way we can directly look up the piece of code that interests us without going through tons of irrelevant data.



Seperation

In the earlier days it was customary to embed scripts inside the Html content. As the years went by, with the improvement of browsers JavaScript engines the use of JavaScript increased dramatically and the scripts volume grew accordingly. Nowadays, separation of the JS code to external JS files will produce a much cleaner and readable Html.



NameSpacing

In JavaScript much like in C, we can add variables to the global scope. For instance we can write the line x = 3 anywhere in the code, then after the evaluation of this line by the interpreter we can successfully reference x from anywhere. When working side by side with external JS code, this can cause naming collisions.
A good solution for this issue is to use namespacing


Let’s look at the following example:

var MathExtensions = {
    PI : 3.14159265,
    Add: function (a, b) {
        return a + b;
    },
    ...
}

In this example we use the JavaScript object literal syntax to create a namespace. The variable PI lives inside the MathExtensions context. To reference it, we’ll have to write :
MathExtensions.PI.

 Same goes for the method Add, we’ll have to use:

MathExtensions.Add(3,5).

For those who come from the statically typed languages world, this may resemble a static class. 
*Note: One may also notice that the value of MathExtensions variable is in fact a valid JSON (Java Script Object Notation).  



Constants

It is almost always a good idea to use constant variables to avoid magic numbers and strings inside the code, especially strings that represent Html classes or IDs.
It was more than once that I encountered lines of code that look like this:

var element = document.getElementById("ActionButton");

or JQuery equivalent:

var element = $("#ActionButton");

If one day we decide to change the ID (or class) of an element (which may happen in web design), we’re in for a risky adventure of tracking down all the references to this element’s ID in the code and change them.

A better way would be to store all these magic strings in variables. A namespace for classes or IDs is advisable. For instance, for the example above we’ll use something like this:


var Classes = {
    ActionButtonID: "ActionButton",
    InputTextBoxClass: "InputTextBox"
    ...
};

The reference will change to:

var element = $("#" + Classes.ActionButtonID);




DRY

The last example emphasizes the practice of a very important principle in programming called the DRY principle. DRY stands for ‘Don’t Repeat Yourself’, but what it really means is ‘One Place To Change’. In the example, when we want to change the class name for an element we’ll change only the value in the Classes namespace.
Do not hold multiple pieces of code that do the same work. If you come across a situation in which you need the same JS code in two different web pages, do NOT duplicate it. Instead, you can hold a shared scripts JS file and reference it from both pages.



More to come in part 2








4 comments:

  1. In most libraries, as well as with javascript core libs, method names are starting with lower case while 'class' methods in upper case. Why did you choose to deviate, i.e. method names to start with upper case?

    You're trying to emulate constants in javascript, a good idea. Won't it be better to add some privacy as in:
    -----------------
    var CONSTANT = function (status) {
    return {
    get: function ( ) { return status; }
    };
    };

    var Classes = {
    ActionButtonID: CONSTANT("ActionButton"),
    InputTextBoxClass: CONSTANT("InputTextBox)"
    ...
    };
    -----------------
    Naturally you can think about having the get() escape the ids (jquery will blow if the id contains unescaped ':'), add the hash tag etc. The best thing about this pattern is letting readers of the code know its a constant they're messing with.

    ReplyDelete
  2. I actually like this pattern. You can add all kinds of getters to the same constant.

    Thanks.

    ReplyDelete
  3. The point is that 'status' is captured in the closure and can't be modified (its private). Naturally you can replace it with another constant, a workaround (still not perfect) would be to have the constant container (Classes) be unmodifiable as well.

    ReplyDelete
  4. Not really sure what the 'another level of indirection' is needed and what problem it solves.
    Both of these
    Classes.ActionButtonId.get();
    Classes.ActionButtonId;
    are just as modifiable and just as safe. The first one just gives you a false feeling of safety.

    I prefer to place my constants in something that looks like:
    MY_NAME_SPACE.constants.ACTION_BUTTON_ID ,
    which is just as safe as the two patterns above, but is crammed with "do-not-modify-this" signs to prevent wrongful modification.

    ReplyDelete