27 May 2008

My JavaScript "rules"

In my day to day life, I see a lot of JavaScript code. I see a lot of code written by others and a lot of code which I have written in the past. As I look back over my own code and my coding style over the last 2 years or so, it is easy to see how far I have come and how much better my code is now.

None of this is meant to suggest that it cannot be improved. Nor am I saying that it is even that good! But, I thought it might be useful to talk about some of the ideas I have employed. These are my JavaScript "rules". I try to apply them in everything that I do:

1. Be unobtrusive
This is an absolutely imperative and key rule. Unobtrusive JavaScript code is easier to read, easier to write and is encapsulated within a JavaScript layer in your application. Writing unobtrusive code means having no JavaScript in the markup of your documents. Make use of browser events (onLoad, DOMContentLoaded etc) to apply the JavaScript enhancements to your pages. Use ID's and if necessary classes to pick DOM nodes from the document to work with.

2. Name your spaces
Namespaces make for much friendlier JavaScript. If nothing else, a namespace will stop you polluting the global scope of the document. I always have one root namespace for an application and then other namespaces off that to define the functionally different regions of your application. Always group similar functionality. If for example you have a bunch of objects which are used for handling forms and form validation, group them all under a common namespace. Creating a namespace is as easy as creating an object. Here is an example of creating a root namespace and 2 sub-namespaces:

var Nortools = {};

Nortools.Login = {};

Nortools.Forms = {};



3. Cry over spilt milk
I always encapsulate functionality within relevant objects and namespaces. Dont let that functionality spill out of the object or the namespace. Use private members in objects to hide the secrets of an object and strengthen your code. This will prevent your application from being changed or interfered with in any way by other JavaScripts on the page. I use self executing functions to create completely closed and hidden objects, neatly encapsulating my code. It is even possible to have private members on the prototype of a constructor using this technique:

var myConstructor = function() {};

myConstructor.prototype = new (function() {

    var myPrivateMember = "some value";

    this.getPrivateMemeber = function() {

        return myPrivateMember;

    }

});


This code may look odd, but the prototype of myConstructor is now a self creating singleton object which cannot be forced to give up its secrets. I use this technique for creating all singleton objects - its encapsulated!

4. Separate
I always separate the various types of code in my applications strictly. If I am dealing with data, I create a data layer to manage all that logic with as few public methods as possible. If I have business rules, the same applies. All presentation logic should also be self contained and independent of the data and the business rules which translate that data into objects which can then be displayed.

5. I object
Use objects and use them extensively. I never store any value within global scope and with everything in a well organised object model, you always know where things are. Use the singleton pattern above (or the many others which are just as good) to create singleton objects - an object that only has one instance.

6. JSON
JSON is extremely useful and powerful. I always use JSON for storing and transferring data in my applications. I also make extensive use of object notation for providing options to my objects. Passing in a JSON object to a constructor can be much easier than handling optional parameters. This is one method for handling optional parameters:

var myConstructor = function(param1, param2, param3) {

    param1 = param1 || "defaultValue";

    param2 = param2 || "defaultValue";

    param3 = param3 || "defaultValue";

};

var myInstance = new myConstructor( "value", null, "value" );


With this method, on creating an instance, I have to know which parameter is which and what order they are in. Its also slightly clumsy looking.

My preferred method is:

var myConstructor = function(options) {

    var param1 = options.param1 || "defaultValue";

    var param2 = options.param2 || "defaultValue";

    var param3 = options.param3 || "defaultValue";

};

var myInstance = new myConstructor( {

    param2: "value",

    param3: "value"

} );


Much neater and I find it much easier to understand and read.

7. Be a detective
I always try to code defensively. I dont want errors to even be possible in my code. To this end, I always want to detect whether the operation I am about to perform is possible. Sometimes this means checking my own objects for a feature, sometimes a built in object. This is much more effective than user agent sniffing for browser features. Not only do I not have to know what each specific browser supports, but I also do not have to keep changing my code each time there is a new version of a browser. It makes my code future proof!

if (document.getElementById) { //check the browser supports getElementById

    var myElement = document.getElementById("myElement");

    if (myElement) { //check an element was found

        //perform some action

    }

}



8. Lets go native
Always use native functionality when its there. Its the fastest method. If you want to have a getElementsByClassName function in your application, check if the browser already has it built in and use that method if it is there. Replacing it will only make your application slower.

9. Delegation's what you need
Events are very important when building web applications. But adding event handlers to lots of nodes can be bad for performance and lead to management overheads. If for instance you have a list of items and clicking on an item in the list performs an action, consider adding the click event to the parent of the list items and using a delegation pattern to handle the event. For a more detailed explanation see this excellent article.

10. Get organised
I always try to organise my code well. It is vital during a build phase of a project to be well organised. I only ever put one object or constructor in a JavaScript file and I name the file accordingly. If the full path (taking into account namespaces etc) to my object is MyApplication.ApplicationSection.ObjectName, then I will name the file MyApplication.ApplicationSection.ObjectName.js. In a large application, my folder structure will represent the namespace hierarchy as well.

Choose a coding style for your application and stick to it. I have my own coding style with naming conventions etc, and I always stick to it. It makes the code more consistent and easier to read and understand.

Comment code wherever it is needed to help understand why the code does what it does. Dont comment code when the comments will not add to the understanding of the code.

11. Dont panic
Writing JavaScript is hard. Writing web applications is harder still. Dont panic. Help is at hand. Use a library.

24 May 2008

JSquared 1.1 Beta 1

Just a quick note to point you to information regarding the release of JSquared 1.1 Beta 1.

14 May 2008

Usability and accessibility

In recent weeks I have been spending much of my time at work thinking about usability, commenting on it and trying to convince others of my ideas.

This thought has been focussed almost solely around two tasks. The first of these was an interesting proposition - to demonstrate that projects previously completed using Flash could be built using JavaScript. As a useful by-product, I have been able to make some more use of JSquared and particularly my alpha build of FXSquared!

There were two particular products that I have been looking at, the first of which was a finance tool for Fiat. I spent 2 days working on this task and as such was only able to make part of this tool.

I started by building the dials which are the main control for the tool. This involved building a number of animations and some simple interactions. I then worked on the panel which flashes as the values change. Amazingly, in only two days, I was able to match all the functionality of the dials and get the values updating in the panel and get the panel to flash.

Accessibility was not an important consideration however, when reviewing the work I was able to complete, the markup I had written was valid and semantic and the product fully accessible. It was certainly no less usable than the Flash, and due to the keyboard being able to control the tools, it was perhaps more usable. It was accessible and worked without CSS and could be made to work without JavaScript very simply. It was a triumph.

The other product I worked on, was in a similar vein and was a similar success.

The original project manager on the Fiat project could not tell the difference between the two products and it was entirely cross-browser.

The point I am making here is that by writing the tool using semantic HTML and progressively enhancing the code with CSS and JavaScript, I was able to make something more accessible and more usable all at the same time.

My second key experience was joining a project that had a significant development effort behind it already. I was asked to point out where I thought the product was not usable. I found myself pointing out 8 areas that I had issue with. When I took a step back and looked at these comments I realised how each of them could also have appeared on a list of changes to make the product more accessible!

These experiences have really driven home for me how closely linked accessibility and usability are and how investing in one will inevitably be investment in the other. What a great selling point for spending more effort on these vital areas that are sometimes overlooked by clients.

11 May 2008

The JSquared blog

I am excited to announce the launch of the JSquared blog - http://blog.j-squared.info/.

From now on, this blog will discuss general web interface development issues whilst the JSquared blog will discuss features of JSquared and provide news of updates etc. You will see the latest few items in the left pane of this blog as well for convenience.

I have copied over the relevant posts to the JSquared blog. Please let me know if you have any comments.

8 May 2008

JSquared update

First of all, apologies for the sparsity of posts in the last few weeks. Its been a busy couple of weeks, but there is plenty to discuss. More of that to come in the next week or so.

The big news however is that JSquared has a new home - www.j-squared.info. There will be a major update to the website to coincide with the release of JSquared 1.1 in late June or early July. JSquared will have its own blog, freeing this blog for non-JSquared related topics generally. More on that in time to come.

An update on the progress of the goals for release 1.1:

JSquared Testing Platform
Using JSUnit, I have had much success testing JSquared. I have about 20% code coverage in the core library so far. My aim is still to have full coverage of the core library for version 1.1

Documentation
Using JSDocs, I have documented around 40% of the core library and I am getting close to a full API reference. This will be available along with a quick start guide for JSquared 1.1

FXSquared
The core FX library is complete. It is based on plugins and I am working on two plugins. I have been using the FX library for a few weeks now and it is nearly ready for release. It will be released with JSquared 1.1

IE 8 Beta Support
There has been some work on general compatibility updates and JSquared continues to improve. It is unlikely that JSquared 1.1 will be fully tested and working on any beta platform, but there will be compatibility updates to help with IE 8 and Firefox 3 support as well as improved Opera 9.5 support.

I hope you are as excited as I am by these updates and new developments. JSquared work continues at a good pace (despite protests from my wife) and I am hoping to increase the usage of the library over the remainder of the year.

Just to keep you all excited, Chris Heilmann gave a talk at AKQA last week and he has posted about it.