Good Practices for Rich Web Applications

Use jQuery

jQuery is the best thing that has happened to Javascript since it got first class functions in version 1.2. The library is elegant, powerful and has exactly the right level of abstraction for working with the DOM. There is nothing more to say. Learn it and use it. Good resources are: the jQuery API, my view of the jQuery API

Learn Javascript

Javascript is the programming language of the web. Learn it! Javascript is different from most other programming languages. It is dynamic, it has prototypical inheritance, and works more like Scheme than any of the languages that you are probably used to. If you want to learn Javascript you should get the following books, The Little Schemer, The Seasoned Schemer, Javascript, the Good Parts, and possibly High Performance Javascript

Learn CSS

Many programmers think that CSS is the language of designers and not programmers. This is not the case at all. If you are lucky enough to have a designer on your team (most people don’t), CSS is the language with which you communicate. It is the interface between designers and programmers and as a programmer you should know it better than the designers. By knowing CSS well you will reduce the misunderstandings between you and your designer.

Unfortunately, many designers don’t care about how code looks, as long as the design looks good on the surface. It will be up to you to make sure that the CSS doesn’t get out out of hand. It will also be up to you to keep the HTML clean, and a good way to do this is to use semantic HTML, combined with CSS. You have no idea what the designers can come up with.

<!-- 
  Old School rounded corners, invented by a GOOD designer. 
  All this code was actually needed to achieve the purpose.
  -->
<style>
.t {background: url(dot.gif) 0 0 repeat-x; width: 20em}
.b {background: url(dot.gif) 0 100% repeat-x}
.l {background: url(dot.gif) 0 0 repeat-y}
.r {background: url(dot.gif) 100% 0 repeat-y}
.bl {background: url(bl.gif) 0 100% no-repeat}
.br {background: url(br.gif) 100% 100% no-repeat}
.tl {background: url(tl.gif) 0 0 no-repeat}
.tr {background: url(tr.gif) 100% 0 no-repeat; padding:10px}
</style>
<div class="t">
  <div class="b">
    <div class="l">
      <div class="r">
        <div class="bl">
          <div class="br">
            <div class="tl">
              <div class="tr">
                Lorem ipsum dolor sit amet consectetur adipisicing elit
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

As an additional benefit you will become better at jQuery. Not only is CSS the query language of the browsers it is the query language of jQuery. Jariba!

Bulletproof Web Design is a good book web design, including CSS.

Decide how “Rich” your application should be

How rich should your application be? The scale varies from no Javascript to only Javascript, but you will probably want to land somewhere in between. Here are a few suggestions.

  • No Javascript, everything is server generated.
  • Slightly enhanced pages, simple validations, but no Ajax.
  • Ajax enhanced pages, but every page still reloads frequently.
  • Single page per area, entire area is handled by Javascript.
  • Only Javascript, Ajax interaction with the server
  • Only Javascript, no interaction with the server.

The important thing is to make a decision. If you don’t make the decision, everyone will do different things on different parts of the application and you will loose consistency. In GUI, consistency is king. Make a decision and move on, you can always change your decision later.

Organize your code

Javascript

Make sure that all your Javascript code is namespaced properly. It is impolite to pollute the global namespace and it will bite you in the end. A simple variable declaration will do.

// Common namespace for your entire application
// This declaration lets you split your code of multiple files.
// If MyNamespace is defined use it, otherwise declare it.
MyNamespace = window.MyNamespace || {};

But, of course, it is also possible to get fancy and encapsulate the functions that you don’t want to expose, if that is your cup of tea.

MyNamespace = window.MyNamespace || {};

MyNamespace.Tournament = function() {
	// Private stuff
	var tournamentCount = 0;
	function addTournament(tournament) {
		tournamentCount++;
	}

	return {
		//public stuff
		numberOfTournaments: function() {
			return tournamentCount;
		}
	}
}();

You should also separate your Javascript code into different files. The namespace idiom above helps to have the same namespace across multiple files. The same principles as with other type of code is valid with Javascript, organize the code by area, when it changes, where it is used, etc. Don’t be afraid of the additional load time, splitting the files will give you. The files can easily be concatenated with tools like Rake, SCons, Ant or even a simple:

$ cat file1.js file2.js file3.js > all.js

They can also be compressed with JSMin or YUI Compressor.

Optimize your environment for development, not for production!

HTML

HTML is code! Divide your pages into partials by responsibilities. It allows you to keep your pages DRY and readable. The Single Responsibility Principle applies to HTML too.

Make sure you keep the Javascript with the code that it manipulates. If you, for example, have a calendar partial that uses jQuery DatePicker, you have to make sure that the partial includes all the necessary Javascript to configure the calendar. Don’t keep Javascript code in the page away from the partial. Things that change together should be together.

CSS

Stylesheets are code too. They should also be split into areas that allow you to easily find and navigate them. Use Sass or SCCS to keep your CSS files DRY. Sass is good for designers to. It gives them the ability to use variable names, mixins, etc. and simplifies their usage of semantic names such as notice, and sidebar instead of yellow and left.

Optimize your environment for development, not for production!

Separate your Javascript from your HTML

All too often I see generated HTML pages with Javascript code in them. Don’t do it. Keep the HTML free from Javascript.

<!-- DON'T DO THIS!  -->
<button id='update-button' onclick="MyNamespace.updateList();">Update List</button>

// In the Javascript file for the page.
MyNamespace.updateList = function() {...}


<!-- DO THIS! -->
<button id='update-button'>Update List</button>

// In the Javascript file for the page.
MyNamespace.updateList = function() {...}

$(function() {
  $("#update-button").click(function() {
    MyNamespace.updateList();
  });
});

It may seem like there is a lot more code in the good example, but notice the symmetry. The code that attaches the listener is in the same file as the code that uses the listener. This is good. Symmetry is good.

Use clone()

Separating the HTML and the Javascript goes both ways. Don’t generate HTML code in Javascript. It doesn’t matter that it is super simple to do it using jQuery.html(). Keep them separate, use jQuery.clone() instead.

// DON'T DO THIS
$("<li data-id='123'>My new item</li>").appendTo("ul");
// OR THIS
$("ul").append("<li data-id='123'>My new item</li>");


<!-- DO THIS -->
<ul>
<li id="list-template" class="template">All .template are hidden (display: none) in the CSS</li>
</ul>

// AND THIS
var $clone = $("#list-template").clone();
$clone.attr("data-id", "123").text("My new item").removeClass("template");
$("ul").append($clone);

The point of this is, again, to keep the HTML separate from the Javascript.

Decide how content flows between, the page, Javascript and the Server.

Once you have decided how rich your application should be, you have to decide on a method for moving the data between the HTML Page, Javascript and the Server. My preferred choice is to have every page that is served from the server include a context object with all the static data for the page and to have additional data that belongs to parts of the page be sent as data-attributes on the elements concerned.

The context object will contain all the data that is commonly needed in the page.

// Sample context object that is generated with the page.
MyNamespace = MyNamespace || {};
MyNamespace.Context = {
  user: {
    id: "28",
    name: "Anders Janmyr"
  },
  tournament: {
    id: "78344",
    name: "Fifa World Cup"
  }
};

I use the context object(s) to keep state on the client to. If it is important that the page looks exactly the same, even if the user reloads the page, I make sure that the state I stick into my context object is synched back to the server. This can easily be done, asynchronously, with Ajax and does not affect performance noticeable.

Elements specific data is sent along with the element it defines.

<!-- Element specific data attached to the elements with data-attributes -->
<ul id="tournament-menu">
  <li data-id="78344" data-participant-count="64">Fifa World Cup</li>
  <li data-id="666"  data-participant-count="44">Americas Cup</li>
  <li data-id="1464" data-participant-count="32">Rugby World Cup</li>
</ul>

The same argument as with the context object applies, as soon as I change an element in the GUI i need to feed that information back to the server. With elements I usually send the information to the server before updating the GUI, since element specific data is usually permanent data and not just session data.

An alternative solution to the context object above is to use the body element as the data-container, like this:

<body data-user-id="28" data-user-name="Anders Janmyr" data-tournament-id="78344" data-tournament-name="Fifa World Cup">

I tend to use the context object because I find it easier to add functionality to it than to the DOM element.

Only send the data that is needed to the client with the page. The rest of the data should be loaded on demand, with Ajax. Both JSON data and HTML templates can be loaded on demand. There is no need to deliver the entire page at once. Experiment and do what gives the best user experience.

Use file watchers to speed up feedback

If you compare the feedback cycle of Javascript and HTML development to Java and C# development, you are probably very happy with the short, tight feedback loop. This doesn’t mean that you should be content. A feedback cycle cannot be too short.

xrefresh for Firefox and IE, and LiveReload for Safari and Chrome, are a couple of tools that will tighten your feedback loop even more.

Both tools are file watchers that listen to changes for files and refresh the browser when they change. If you combine this with two screens, you will have one screen for the browser, that updates continuously, while you edit your code on the other screen. Fabulous!

Conclusion

Rich web applications are very close to the traditional client-server model. We have to keep state on the client side to give the user a good experience. At the same time the application state, and indeed the entire application, can be swept away by a click of a button or a page reload.

This puts new demands on us as developers. We have to realize that we are responsible for the entire application, not just the business logic, but the HTML and CSS too. More that anything, we have to realize that Javascript is a first class programming language with its own programming techniques, which we need to master to be able to develop good web applications.

11 Comments

  1. Excellent stuff. Especially liked the clone() bit for taking even tiny bits of html out of js

  2. Anders Janmyr
    Anders Janmyr

    @Yaron I’m glad you liked it.

  3. Hi,
    Nice article, thanks for that one. Although, it seem to me that you shouldn’t limit yourself to JQuery. Being honest, way before jQuery i was using Prototype, then, when Scriptaculous broke the ground, i used it for some effects. After that – jQuery, right now – MooTools is the best option for me, but that’s just personal perference.

    Besides that, when developing rich internet application, tons of things pop up. Acceptance testing is crucial. You can use Selenium Webdriver if you’re on any technology. Capybara is a good option for Ruby apps, though i launched it for .net project as well.

    Another thing, which is quite questionable as well, is JSLint. Some people say they can’t live without it, some prefer to go without it, since it’s way too demanding. But if you’re going to compress your javascript, it will save you some time, at least my experience shows that.

    As regards Unit Testing for JavaScript, some people say it’s not quite relevant. Though i do use it for hardcore async operations, since it’s not trivial to cover with acceptance or manual tests, some flows are difficult to track down. I prefer jspec, it has a nice DSL for testing, and works quite well for my needs. Though there’re some other things, such as JSUnit.

    Hope some will find some use for my 2¢

  4. BTW, about 1 year ago I was speaking on a conference about the RIA practices in general, not JS-specific, if you want, you can take a look: http://bit.ly/dekcL8

  5. Anders Janmyr
    Anders Janmyr

    @Alex P, Thanks for your feedback.

    > Although, it seem to me that you shouldn’t limit yourself to JQuery.
    I agree with that, I just use jQuery as my first option, I often combine it with other libraries, such as Prototype and YUI. I also heard great things about Dojo, but I haven’t had the time, or the need, to explore it.

    > Acceptance testing is crucial.
    I like to use Cucumber, in combination with Capybara, and Selenium for acceptance testing.

    >JsLint
    I disagree with some of the settings of JSLint so I don’t use it. I should probably just tweak it to my liking and start using it.

    > As regards Unit Testing for JavaScript
    I currently use QUnit, it is simple and good enough. I used to use Scriptaculous Test, and it is also quite good. I’ll take a look at JSpec, I assume it looks like RSpec. BTW, ScrewUnit is another an RSpec clone, and I like that name better :)

  6. Anders Janmyr
    Anders Janmyr

    @Alex P, Nice presentation! :D

  7. This is good article. Now we have so many client side html templates through which we can keep our client side clean by separating HTML and java script.

    https://github.com/jquery/jquery-tmpl

Trackbacks for this post

  1. Tweets that mention Good Practices for Rich Web Applications — Jayway Team Blog -- Topsy.com
  2. Random Links #248 | YASDW - yet another software developer weblog
  3. Destillat #53 – Web- und Softwareentwicklung | Open Source und Wetware
  4. Dynamic FTP Client Using Apache Camel | Allen Solly

Leave a Reply