Tuesday, March 20, 2012

One does not simply inherit into objects

I used to implement prototype inheritance in JavaScript in order to share behaviour between objects. That's a clean way of creating components (widgets since now) and it provides a basic structure that also helps organizing your code.

I worked in large RIA projects with tons of JavaScript code, and I also worked in common request/response-based projects with rich components where also was a lot of JavaScript code. In both cases I took part in infrastructure decisions and I remember myself being of the "let's use prototyped classes to structure our code" guys. This is my mea culpa :)

After a while I learnt that inheritance in JavaScript isn't like in Java. And the common mistake is to think an object model in JavaScript like if we were coding Java (or another strongly-typed object-oriented language). Don't blame yourself, I know you found a lot of JS libraries that tell you that it is good, they bury into your mind that you've got to build classes and they have to look like in Java. So we find things like this:

MyClass = Class.create({
  _message: null,

  initialize: function (message) {
    console.log("Hi!, I'm a constructor");
    this._message = message;
  },

  talk: function () {
    alert(this._message);
  }
});

I didn't write comments in the code because I want to show how odd and weird it is without any noise.

First of all, note that a "private" attribute is prefixed with underscore (_message). It is what I call "the private trap". It implies:
  1. We only trust in a weak convention to indicate that an attribute is private, but we're exposing it anyway.
  2. At the end of the day, when you're enough broke to respect conventions and you need to deliver a product next morning, you will not tremble to change "private" values, which can be a catastrophic mistake since it can be shadowing design limitations.  
  3. The most important: you cannot think in terms of software design.
The second consideration is that there exist a "virtual constructor". This is often defined as a convention by libraries since it's not possible to implement transparent prototype inheritance with native constructors. This approach has the following issues:
  1. It's not standard. Usually it changes from library to library, so you cannot simply reuse code without adding required libraries, which sometimes aren't compatible between them.
  2. It's not clear for people that don't know the library you're using. There're some considerations regarding objects lifecycle that need to be well-understood before start working on a class.
  3. Conventions proliferate everywhere. Conventions are out there to help us understand between us, if they make our work harder, they should be removed.
There're at least two different stages to implement a solution: design time and implementation time. In the design time you think about the problem, split it up into small pieces, you trace the relationship between them and finally you decide the high level structure of your solution. At this point you didn't write even a line of code.

I'm not saying that you cannot design well by using this pattern, I'm trying to tell that this pattern actually induces you like a devil to stop thinking and start coding before you understand what you need to solve. The threshold to do not stop and think is very low.

This pattern also aborts several good practices and design principles. For example, you cannot design thinking in "providers and consumers". You cannot document contracts because all the public interface is full of useless fields.

You need to bind every method to the object (sometimes more than once) to make the instance available in callbacks. Usually the DOM Event Model is broken because the scope in callbacks is not "the object receiving the event" as the spec says, but the object instance. It's not just about keeping standards, it also may cause memory leaks impossible to track, or it may cause annoying bugs like event handlers registered more than once.

And of course, all user-related interaction methods like event handlers are mixed into the object together with the business-specific logic. You cannot make your model agnostic (whatever it means).

I understood some of these concerns implementing classes this way, however I told to myself: this is the truth about make your application to scale up to the sky. And it was a terrific lie. Your application won't scale by using this pattern. You generate a strong coupled set of classes that cannot survive alone. You easily fall into the yo-yo antipattern, and it can be an unrecoverable mistake in JavaScript. It often results in an anemic model that adds accidental complexity to your codebase, making very harder to refactor what already exist.

I like to compare this pattern with writing in stone.

More or less that was the scenario when we decided to change our minds and find a solution to these problems. After several discussions and research, we agreed with the following pattern:

MyClass = function (message) {
  console.log("Hi!, I'm a constructor");
  return {
    talk: function () {
      alert(message);
    }
  };
};

Yes, this is the well-known module pattern. Look at the code, it's cleaner, doesn't it?. Let's say something about it:
  1. You don't need to store constructor parameters in private variables.
  2. You can expose only public, defined-by-contract methods.
  3. You can simplify interfaces and think about what's public and what is not before start coding the implementation.
  4. You can easily refactor this code, because the public interface is what consumers see and it's implementation-agnostic. It means that you can safely rewrite the full implementation only respecting the documented contract.
  5. There's no more no function binding. I have been implementing this pattern for some months and there's no one case in which I had to bind a function to an object (yes, maybe you think I'm lying, it sounds like the paradise!).
And what about inheritance? Of course, we need to keep at least the following features provided by inheritance:
  1. Augmentation (inherit methods and fields)
  2. Methods override.
  3. Invoke superclass methods.
This goal is easily reached with the module pattern:

Subclass = function (message) {
  var base = new MyClass(message);
  var talk = base.talk;

  return jQuery.extend(base, {
    feed: function () {
      this.talk("mmm!");
    },

    talk: function (whisper) {
      console.log("Psst: " + whisper);
      talk(message);
    }
  });
};

Note that the implementation is composing the base class MyClass instead of inheriting from it, and the constructor returns a mixin (I'm using jQuery.extend by convenience, but you can implement it yourself) that merges the base object and the new behaviour. It's more like composing behaviour instead of inheriting from classes (and of course, you can compose more than one object into a mixin).

The method-override is also pretty simple. It stores the original method in a private variable, and the mixin just overrides the method and it calls the original from inside. A similar strategy is used to access superclass methods: you can invoke them accessing the base variable instead of using this. That is another level of safety to avoid function binding and it also gives you the idea of composition instead of inheritance.

Opposite to the Writing in Stone pattern, I call it Drawing in the Sand.

Next time you have to structure UI applications think about this. Do I want to write in the stone, or do I prefer to draw in the sand? If you successfully answer this question, you'll be around the KISS principle, that is essential in a mutable-hostile environment like it is a web application.-

Sunday, July 4, 2010

JavaScript Projects Automation

Yes, finally I decided to document something which was rounding my head during several weeks. I noted that every time I have to set up a new UI project I find myself copypasting a lot of odd old configuration instead of making a nice fresh start.

That's why I created an Automation section in this blog. The section will try to cover some aspects related to managing projects in the real world. It will be fully based on true cases: real problems and real solutions. Please feel free to suggest new topics and corrections, any contribution is welcome.

Good look.

Wednesday, June 30, 2010

Evilness Part 3: The Epic Trip of Comparing Data

A common needed is to determine what kind of value has a variable. It sounds easy, but in a weakly-typed language as JavaScript it could become epic.

JavaScript implement two type of comparisons: by value and type, and only by value. What it means?. Let's explain these two comparisons using string values:

var str1 = "asdf";
var str2 = "asdf";
var str3 = new String("asdf");
var str4 = new String("asdf");

1. console.log(str1 == str2); // Prints true
2. console.log(str1 === str2); // Prints true
3. console.log(str1 == str3); // Prints true
4. console.log(str1 === str3); // Prints false
5. console.log(str1 == str4); // Prints true
4. console.log(str1 === str4); // Prints false
6. console.log(str3 == str4); // Prints false
7. console.log(str3 === str4); // Prints false

JavaScript provides two comparison operators for these two types of comparison: equal (==) and strict equal (===).

The equals operator == compares by value. This mean that during the evaluation JavaScript doesn't care about the variable type but in the content. The inquiring readers should be asking themselves: is it possible to determine a variable content without checking the type?. And the answer once again is yes, it is. All objects in JavaScript have a primitive method named valueOf(). When you are comparing two variables by value (using ==), the engine call this method for both operands, and compares the result. Let's see this weird example:

var str1 = "asdf";
var arr1 = new Array();

arr1.valueOf = function () {
  return "asdf";
};

console.log(str1 == arr1);

Against all probabilities this piece of code will print true. Why??, we are comparing a string against an array!!. Yes, but during a value comparison the type, believe me, doesn't care.

Okay, your mind is now looking for ways to explode this potential bug, but we are not careless coders, right?. So let's go to check the other comparison operator: strict equal (===).

Comparing by type and value means that the variable type and the value must be equals. This kind of comparison is not stronger only for the extra (type) validation, but because the engine performs reference validation. Yes, another example here:

var str1 = new String();
var str2 = new String();

str1.valueOf = function () {
  return "asdf";
};
str2.valueOf = function () {
  return "asdf";
};

1. console.log(
  (str1.valueOf() == str2.valueOf()) &&
  (typeof str1 == typeof str2)
);

2. console.log(str1 === str2);

If we try to emulate the engine behavior (as we shown with the == operator) it will fail. In the case (1) the output will be true because it matches our definition: "compares type and value". But the engine performs the extra reference validation and that's why the case (2) will print false.

Of course, as the primitive types (Boolean, String and Number) are immutable objects (their type and values are always unique) and they are the wide-used kind of objects, we often can't take care about this tricky and dangerous behavior.

The last example bring us to the last point of this post: the typeof operator. The typeof operator can be used followed of any variable and it returns a string indicating the primitive type of the variable's value.

var bool1 = true;
var str1 = "asdf";
var num1 = 1234;
var obj1 = {};
var arr1 = [];

console.log(typeof bool1); // Prints 'boolean'
console.log(typeof str1); // Prints 'string'
console.log(typeof num1); // Prints 'number'
console.log(typeof obj1); // Prints 'object'
console.log(typeof arr1); // Prints 'object'

All returned strings are part of the ECMAScript standard, so we are able to use it for validations. But let's focus in the last result from the example:

console.log(typeof arr1); // Prints 'object'

You may be wondering why it prints "object" if the value is an array. Sadly (or not) the ECMAScript standard just defines typeof-results for the primitive types, which are: Boolean, String and Number. Any other kind of value will be interpreted as an object (objects are commonly named "composite types"), and evidently an array is not a primitive type so it's an object.

There's another dangerous behavior with typeof: the primitive types are also constructors which can be used to create objects containing primitive values. For example:

var str1 = "asdf";
var str2 = new String("asdf");

console.log(typeof str1); // Prints 'string'
console.log(typeof str2); // Prints 'object'

Yes, if you create an instance of the String prototype it will be an object, not a primitive string. The more confusing point there is that using the == operator str1 and str2 are equals, but not comparing them with ===.

Okay, stop it. We have a lot of information up to there. Don't be afraid, the comparison difference between primitive types and objects created using the primitive constructors can be unified, but there will be another evilness chapter explaining how the instanceof operator works in JavaScript.

From my point of view, the strict equals must be used whenever we're comparing two values from an unknown source, it is, the most of cases. Leave the equal (==) operator to special and conscious uses.

Good look.

Tuesday, June 29, 2010

Evilness Part 2: Bringing Standards to Heaven

"And what about using for...in to iterate over a primitive Array?"

Okay, it goes like these: 1, 2, 3, FAIL.

Some weeks ago I saw a piece of code that deserve to be translated here:

var info = ["Hello", "World", "I'm", "A", "Fancy", "Array"];

for (var item in info) {
  console.log(item);
}

At first glance it seems to work fine. Because arrays are treated as a composite type (for JavaScript purposes it's always an object: a data type that can consist of multiple values grouped together in some way), it can be easily iterated using a for...in loop. What's wrong then?

"Treated as an object" implies more than a simple array. Yes, we're falling again in the First Known Evilness. This mean that the loop will iterate through the whole prototype, and the difference is just which prototype is used. In the first-evilness case the primitive Object's prototype is iterated, while in this case the Array's prototype is used. The result is the same, we're taking non-desired values.

So you must be wondering why don't we use the same workaround than in the first-evil case. The answer is that there's an issue in the IE implementation of the ECMAScript standard. The standard specified that the length property of any array object must be inherited from the primitive Array's prototype, which means that we could filter the loop against the hasOwnProperty method and it would work right. But not, sadly not. IE implements this property as an own property of the array object. Let's see which will be the output in IE:

var info = ["Hello", "World", "I'm", "A", "Fancy", "Array"];

/*
  Gecko, Webkit, etc, prints: 0, 1, 2, 3, 4, 5
  IE prints: 0, 1, 2, 3, 4, 5, length
 */
for (var item in info) {
  if (info.hasOwnProperty(item)) {
    console.log(item);
  }
}

Weird but true. So, to avoid this kind of problems please don't use a for...in loop to iterate over a primitive array object (or lead the MS guys to release a hotfix for all IE versions; or both!). Using the common for loop we completely forget about this issue because the control variable just will be increased until it reach the max value:

var info = ["Hello", "World", "I'm", "A", "Fancy", "Array"];

for (var i = 0, j = info.length; i < j; i++) {
  console.log(info[i]);
}

In the next evilness chapter we will discuss why the typeof operator may be just... evil, and how to safely determine the primitive type of a value.

Good luck.

Monday, June 28, 2010

Evilness Part 1: The Damn Looping

One of the most common cases where the evilness break whatever we coded is when we use for ... in without taking into account what JavaScript does to deal with it.

Look at the following tiny code chunk:

var obj = {
  foo : "Hello",
  bar : function (msg) {
    alert(msg);
  }
};

for (var field in obj) {
  alert(field);
}

The previous code will show two alerts ("foo" and "bar"), as it's expected. Now let's see the following piece of code:

Object.prototype.evil = "Prototype chainevil-ity";

var obj = {
  foo : "Hello",
  bar : function (msg) {
    alert(msg);
  }
};

for (var field in obj) {
  alert(field);
}

This seems to be the same code as the shown above, but it's not. Now it will show three alerts ("foo", "bar" and "evil") because the for...in statement goes through the whole prototype chain.

I mean, if the primitive prototypes are extended with new properties and methods, these new properties and methods will appear in the for...in loop for any instance created from those primitive prototypes.

So, is it possible to safely enumerate properties?. And the answer is yes, it is. JavaScript provides a method named hasOwnProperty that any kind of object or composite type has.

Using this method we can check if an object contains a field in its own instance, without checking the prototype chain. This mean that we are able to deal with this kind of evilness using this method, as it's shown below:

Object.prototype.evil = "Prototype chainevil-ity";

var obj = {
  foo : "Hello",
  bar : function (msg) {
    alert(msg);
  }
};

for (var field in obj) {
  if (obj.hasOwnProperty(field)) {
    alert(field);
  }
}

// Shows an alert saying "Prototype chainevil-ity".
alert(obj.evil);

Yes, it works as the first piece of code but you are still able to use the evil property because it's a member of the object's prototype. This applies both for properties and methods.

And what about using for...in to iterate over a primitive Array? This is another kind of evilness and it will be covered in the next blog entry.

Good luck.