Working with a load of JavaScript

December 20th, 2011 by Filipe Sabella

The last project I worked on revolved around a unique and feature rich screen.

After three releases and one year of work, it ended with around twenty thousand lines of JavaScript for that screen alone, and another five thousand for the rest of the application. The line count for the C# backend stopped at nineteen thousand.

25k lines of js, 19k lines of c#.

Well, the title of this post if probably missing a word, but I’m trying to keep this thing curse free.

This screen has one interesting aspect: almost no ajax calls are needed, so all the logic and state have to be handled by js alone.

Most things and practices approached on this project probably wouldn’t fit js on a smaller scale. If fifty lines of script solves your screens problem, it doesn’t require a domain model – and be grateful for that, trust me.

The team learned a few things as the project progressed, and I’d like to share some of these with you.

Don’t use global events

This one was hard. We started with a very basic event hub for all the events on the screen. That seemed fine at the beginning, but as any desktop developer knows, when screen state dictates what events should be fired, things start to get out of control.
In the end we favoured a simpler approach where the model itself fires high level events:

function Document() {
    return $.mix(observable(), {
        addFile: function (file) {
            // logic ...
            this.fire('fileAdded', file);
        }
    }
}

function Sidebar(document) {
    document.on('fileAdded').execute(function (file) {
        // rerender itself
    });
    return { … };
}

Use GUIDs wherever you can

One aspect of the screen that led to very poor code was the problem with entity identifiers.
When the user adds a new entity on the screen, we assign a negative unique integer ID to it so we can work with the object.
However, when the user saves the screen state, the database assigns positive, real IDs to all the entities.
On the way back to the screen we had to update all the stored state with the new IDs. Messy.
If we worked with GUIDs for all the entities, we could generate the final IDs on the client side, since the logic to create them is can be easily written in js as well.

Encapsulation will save you in the end

Don’t use public properties, encapsulate every bit of exposed data through functions, and exposed data should only be used for displaying it:

function Image(id, name, file) {
    return {
        id: function () { return id; },
        name: function () { return name; }
    }
}

This is one of the many practices that we as software developers are used to, but for some reason forget them when writing client side js.

Favor immutability

Dealing with state stored on the client side can become very messy very fast, immutability will help you a great deal.
If you have immutability you can do cool stuff like this:

_.prototype.get = function (v) {
    return function () {
        return v;
    }
}

function Item(id, name) {
    return {
        id: _.get(id),
        name: _.get(name)
    }
}

If your values are mutable this wouldn’t work.

Bind when creating

Avoid this:
images.each(function (image) {
    var li = $(' <li></li>').attr('data-id', this.id());
    container.append(li);
});

$('li', container).click(function () {
    var id = this.attr('data-id');
    view.dialogs.openImage(id);
});

In favor of this:
images.each(function (image) {
    var li = $(' <li></li>')
    li.click(function () {
        view.dialog.openImage(image);
    });
    container.append(li);
});

It looks obvious on this small example, but if you find yourself storing entity data on the markup, there’s a very good chance that your code isn’t being executed on the right scope.

An exception to this is when performance becomes an issue because of too many binds. $.delegate helps a bunch when this happens, but you’ll need to rely on data inside the markup.

Inheritance can hurt

function Entity(id, name) {
    return {
        changeName: function(newName) {
            name = newName;
        }
    }
}

function Document(id, name, file) {
    var api = {
        extension: function () {
            return file.split('\\.').last();
        },
        render: function (renderer) {
            return renderer.render(id, name, file);
        }
    }

    return $.extend(api, new Entity(id, name));
}

var doc = new Document(1, 'the document', 'file.pdf');
doc.changeName('the new document');
doc.render({
    render: function (id, name, file) {
        // BUG: receives the old name
    }
});

When we call doc.changeName(), the parent function on Entity is executed.
However, the Entity function changes its scoped “name” variable.
When we call doc.render, its scoped “name” variable still contains the old value.

To fix this, we’d have to declare a getter for the name on the parent entity, and the “name” variable on Document is useless and dangerous.

Avoid small tricks with element identifiers

<input id="field-id" />
<input id="field-name" />
<input id="field-email" />

function validate(field) {
    var val = $('#field-' + field).val();
    // ...
}

validate('id');
validate('name');
validate('email');

That small concatenation of the inputs IDs is a very common example of programmers trying to avoid a bit of duplication.

Avoid small tricks.

On a large codebase a part of your day revolves around finding element identifiers on files.
A common operation:
1. Inspect element with firebug to find its id
2. Go to IDE and search all .js files for given id to see who’s working with it

Keep the DOM away from your domain

Yep.

Hope this helps.

Does syntax affect readability?

May 2nd, 2011 by Filipe Sabella

Sometime ago I had a quick discussion with a colleague about this line of code:

errors.length == 0 && submit();

In his view, this wasn’t readable – being readable code that which doesn’t need translation, or as little as possible.
He argued that the code would be much better expressed like this:

if (errors.length == 0) {
  submit();
}

Thinking about this discussion, my understanding of his point of view was that the JavaScript’s shortened syntax sacrificed readability, making the reader translate the first version into the second in order to understand the meaning of the code – which is, in this case, “submit if there are no errors”.

I agree with him that the code’s intention should be made clearer. We could achieve that by assigning a new name:

var isFormValid = errors.length == 0;

 
And perhaps changing the other one:

submitLoginForm();

 
But I disagree completely that syntax alone may decrease code quality. My understanding is that such statement could be used to say that using the English contractions (do not – don’t), or even the spoken French liaisons also diminishes the understanding of the receiver.

Syntax is a matter of habit and understanding – and it also may provide shortcuts.
Names, on the other hand, can define meaning to operations.

I would go for this code:

var formValid = errors.length == 0;

formValid && submitLoginForm();

 

And you?

One line ifs and literate programming

October 8th, 2010 by Filipe Sabella

A collegue of mine, Vinicius Gomes, exposes in this blog post reasons to have one line if blocks.

Following up with the discussion he started, I would like to show a technique to apply that concept in a more literate way in JavaScript.

One way to enforce this pratice and end up having more readable code is to extend the JS Function object, adding a behavior that is found in other languages, such as Ruby.

Paraphrasing his example:

function died() {
	return tries > 10;
}

function gameOver() {
	alert("You lose :(");
}

With these two functions, we would normally write something along the lines of:

if (died()) gameOver();

But we can expand the language and write something like:

gameOver.if(died());

Unfortunatelly “if” is a keyword in JS, so we have to improvise. We can search for suitable alternatives:

gameOver.when(died());
gameOver.givenThat(died());

I don’t really like the “when” word, since it could mean the scheduling of a task, but for now it’s the shortest implementation I could think of without recurring to “_if”.

Implementing this is quite simple:

Function.prototype.when = function(bool) {
	if (bool) return this();
}

Or the shorter way:

Function.prototype.when = function(bool) {
	return bool ? this() : undefined;
}

Following this line of thinking we can also easily implement “unless”:

Function.prototype.unless = function(bool) {
	return !bool ? this() : undefined;
}

But what if our function has parameters?
We can do this:

var validateContactForm = function() {
	return validate($('#contactForm'));
}
validateContactForm.when(validationIsEnabled);

Or the shorter way using function currying:

var validateContactForm = validate.curry($('#contactForm'));
validateContactForm.when(validationIsEnabled);

What are your thoughts about this?

New Mouse Cursors

February 24th, 2010 by Filipe Sabella

Inspiration

This is something that you should read if you’re interested in usability: Mixing Games and Applications.

The author states that the software developing world has much to learn from the world of games, and I agree wholeheartedly.

For me the high point of the presentation is when the author shows the basic model for applying exploratory learning:

“You have a goal, skill in the user’s head, tools and actions they take in the application, rules that the application executes and stimulus that the application feeds back to the user.”

So what?

If you think about it, software in general doesn’t make much use of different mouse cursors. The most widely used ones are the resize and pointer – both being hugely effective and useful hints as to what to do with the element below the cursor.
Since the web came to be, the little pointing hand became an universal symbol that indicates we can click on something.

For some time now I’ve been thinking of ways to apply the concept of exploratory learning to the softwares I help create. One such way is to explore the mouse cursor.

How?

Let’s say the user’s just filtered a list of clients, and his goal is to see more data about a particular record. He instinctively hovers his cursor over the desired record and the application changes the mouse cursor to this:
double click

He has a goal: see more data.
As he hovers the mouse over the record, the mouse cursor changes – he has a stimulus.
He already now how the mouse operates, so he has the skills to relate to the stimulus.
Now the user does something – probably click once at the record. And nothing happens. Absolutely nothing, he doesn’t get what he wants, but also doesn’t trigger anything bad. Those are the rules.
If everything goes well, he’ll try again and, hopefully, succeed when double clicking the record.

The same spirt could be applied to these other two badly drawn cursors.
One for right clicking:

right click

I chose the pinky to signify a right click and not the middle finger

And one for grabbing things:

imagine really hard that this is a hand grabbing something

imagine really hard that this is a hand grabbing something

If more than one action is possible in the same area with the mouse, things start to get a little complicated. But providing multiple controls on the same object is prone to error and frustration: a square that can be clicked, double clicked and right clicked. We should avoid this kind of solution.

If you feel tempted about animated cursors, please don’t. Repeated animations are sources of irritation, they steal our attention and lose their use after the first time we understand what they mean.

What do you think?

Introducing jQuery Silver

July 10th, 2009 by Filipe Sabella

Adds quicksilver-like search features for links in webpages. Some web applications just have too many menus and sub-menus – instead of threading your way through them, just hit the (customizable) hotkey, type some of the letters of the target link and hit enter.

Demo: http://www.filipesabella.com/jquerysilver/demo.htm
Project page: http://code.google.com/p/jquerysilver/downloads/list
Source code: http://github.com/filipesabella/jquery.silver/tree/master

Features

  • Works with any <a>, <input type="button"/> and <input type="submit"/>
  • Camel case matching of links
  • Optional storing of last accessed items with jquery.cookie
  • Keyboard navigation: arrow keys, <enter> and number keys
  • Supports custom commands, see the demo

Usage

  • import jquery-1.3.2.js
  • import jquery.hotkeys-0.7.9-1.js
  • optionally import jquery.cookie.js to enable last opened items
  • import jquery.silver-1.0.js
  • import jquery.silver.css or custom css
  • include $().silver() or $(‘#menu’).silver() at jquery startup to initialize
  • hit ctrl+shift+space (or shift+space in opera) to show the dialog

Shortcuts

  • <ctrl>+<shift>+<space> by default to show the dialog
  • <esc> to close it
  • Arrow keys for selecting items
  • <enter> to open selected item or first item if none selected
  • number keys to open the respective item
  • ‘:’ to show available commands
  • <tab> to autocomplete commands

1.1 release notes

  • Added support for image links
  • Added support for commands autocomplete
  • Fixed bug when executing an invalid command

About

I have now learned to hate keyboard events incompatibilities.

The first version for FireFox only took four hours of development. Making it work in Opera and Safari took another eight. Not pretty.

You can find the full source at GitHub.

Suggestions and bugs are welcome.