Tales from the Evil Empire

Bertrand Le Roy's blog

News


Bertrand Le Roy

BoudinFatal's Gamercard

Tales from the Evil Empire - Blogged

Blogs I read

My other stuff

Archives

October 2006 - Posts

ComponentArt on migrating to ASP.NET AJAX Beta 1

Miljan over at ComponentArt wrote his first post explaining how their migration to Beta 1 went (i.e. great, the whole thing was done in four days). He has some very nice things to say about the platform, which we're all very flattered about: "After getting over the initial hump, we found ASP.NET AJAX Beta 1 to be remarkably well functioning and stable."

If you don't know ComponentArt, they are the publishers of one of the best component libraries for ASP.NET, and they're now building it for ASP.NET AJAX. Check it out.

http://blogs.componentart.com/miljan/archive/2006/10/31/ASP.NET-AJAX-Beta-1-and-ComponentArt-Web.UI.aspx

Eilon on UpdatePanel changes

Eilon wrote two very helpful forum posts on the recent changes in UpdatePanel.

What's up with UpdatePanels and how come nothing works? http://forums.asp.net/thread/1440058.aspx

HOWTO: Write controls compatible with UpdatePanel without linking to the ASP.NET AJAX DLL http://forums.asp.net/thread/1445844.aspx

This second article goes in depth on how to use the new registration APIs on ScriptManager, but without linking to the Atlas assembly.

ASP.NET AJAX Beta 1 is out!

It's a great pleasure to announce the beta 1 of ASP.NET AJAX. It is a major release of the product formerly known as Prince Atlas. There are too many changes to enumerate here (we basically remodeled the house), but the idea is to provide a rock-solid core and continue to innovate with the value-add CTPs. I'll blog in the next few weeks on some of the new features, and the first one will be the compat layer, which has been completely redesigned based on your feedback.

We're already hard at work on the next release. I'll keep you posted.

http://ajax.asp.net is the new url for Atlas/ASP.NET AJAX

From closures to prototypes, part 2

In part 1 of this post, I exposed the differences between the closure and the prototype patterns to define JavaScript classes. In this post, I'll show the shortest path to convert an existing class built using Atlas and closures to a prototype-based class. I'll also show a few caveats that you need to be aware of.

Here's an example of a class built using the July CTP of Atlas:

Custom.Color = function(r, g, b) {
  Custom.Color.initializeBase(this);

  var _r = r || 0;
  var _g = g || 0;
  var _b = b || 0;

  this.get_red = function() {
    return _r;
  }
  this.set_red = function(value) {
    _r = value;
  }

  this.get_green = function() {
    return _g;
  }
  this.set_green = function(value) {
    _g = value;
  }
  this.get_blue = function() {
    return _b;
  }
  this.set_blue = function(value) {
    _b = value;
  }

  this.toString = function() {
    return Custom.Color.callBaseMethod(this, "toString") +
        "(" + _r + "," + _g + "," + _b + ")";
  }
  Custom.Color.registerBaseMethod(this, "toString");
}
Custom.Color.registerClass("Custom.Color", Sys.Component);

The first thing you need to do is insert the following right after the private variable initialization, as this is all that's needed now in the constructor:

}
Custom.Color.prototype = {

Then you need to replace the variable initializations in the constructor with instance variable initialization:

  this._r = r || 0;
  this._g = g || 0;
  this._b = b || 0;

The next step is of course to replace all occurrences of _r, _g and _b with this._r, this._g and this._b throughout the rest of the code.

Note the convention that private members (fields and methods) are prefixed with an underscore. This convention will be adopted by Visual Studio Orcas in IntelliSense.

For each method and property accessor, you need to remove the "this." before the name and replace the " = " with ": ". Also add a comma after the closing brace of each method but the last one. Finally, remove any registerBaseMethod you may have (in prototype-based classes, everything is virtual).

That's it, your class is now built using prototypes:

Custom.Color = function(r, g, b) {
  Custom.Color.initializeBase(this);

  this._r = r || 0;
  this._g = g || 0;
  this._b = b || 0;
}
Custom.Color.prototype = {
  get_red: function() {
    return this._r;
  },
  set_red: function(value) {
    this._r = value;
  },

  get_green: function() {
    return this._g;
  },
  set_green: function(value) {
    this._g = value;
  },

  get_blue: function() {
    return this._b;
  },
  set_blue: function(value) {
    this._b = value;
  },

  toString: function() {
    return Custom.Color.callBaseMethod(this, "toString") +
        "(" + this._r + "," + this._g + "," + this._b + ")";
  }
}
Custom.Color.registerClass("Custom.Color", Sys.component);

I've highlighted where the code differs in both samples for easy reference.

So that was easy. Now let's enumerate a few do's and don't's...

  • Do transform private constructor variables into underscore-prefixed instance fields.
    Foo.Bar = function() {
      var _baz = "";
    }
    becomes
    Foo.Bar = function() {
      this._baz: ""
    }
  • Do move all methods and property accessors from the constructor to the prototype.
  • Do update all references to fields and methods to be dereferenced through the this pointer.
    _member
    becomes
    this._member
  • Do separate prototype members with commas, but don't leave a comma after the last one (JSON syntax doesn't allow it).
  • Don't use the instanceof operator with Atlas classes. Do use 
    MyNamespace.MyType.isInstanceOfType(myInstance)
    instead of 
    myInstance instanceof MyNamespace.MyType
  • Do continue to set initial values of fields from the constructor.
  • Don't move field initializations that depend on the this pointer to prototype (but do make them fields)
    Foo.Bar = function() {
      var _delegate = Function.createDelegate(this, this._handler);
    }
    becomes
    Foo.Bar = function() {
      this._delegate = Function.createDelegate(this, this._handler);
    }
  • Don't register base methods: with the prototype pattern, all methods are virtual. The registerBaseMethod will not be available in Atlas starting with Beta 1, which makes it impossible for closure-based classes to be base Atlas classes.
  • Do move private functions to the prototype (prefixing the name with underscore) unless they have a compelling use of the closure pattern (for security for example), which is quite rare.
    Foo.Bar = function() {
      function privateMethod() {
        //...
      }
    }
    becomes
  • Foo.Bar = function() {}
    Foo.Bar.prototype = {
      _privateMethod: function() {
        //...
      }
    }

In the next posts, I'll get into other specific changes that we're making in Beta 1.

Read part 1 here: http://weblogs.asp.net/bleroy/archive/2006/10/11/F...

From closures to prototypes, part 1

There are basically two ways to define classes in BLOCKED SCRIPT closures, where the constructor of the class both adds methods to the new instance and provides a common context for them, and prototypes, which are the first place JavaScript will look at when looking for a member that isn't directly defined on the instance. Don't worry if you don't understand everything I just said, I'll show and explain.

Closures are functions that are defined in a context. This context is the sum of all the objects that are defined at the scope where the function is defined. The catch is that the function not only can access this context, it will also take it with itself everywhere it goes. In other words, closures are functions that remember where they came from. In JavaScript, functions automatically get that quality. Here's an example:

function createClosure(a) {
  var b = 42;
  return function(c) {
    return "a=" + a + ", b=" + b + ", c=" + c;
  }
}

var closure1 = createClosure(1);
alert(closure1(8)); // a=1, b=42, c=8
alert(closure1(9)); // a=1, b=42, c=9

var closure2 = createClosure(2);
alert(closure2(10)); // a=2, b=42, c=10
Coupled with the semantics of the this pointer, closures enable the construction of class instances that have real private variables:
function Point(x, y) {
  var _x = x;
  var _y = y;

  this.get_x() {
    return _x;
  }

  this.get_y() {
    return _y;
  }
}

In this example, we have constructed a truly immutable Point structure. There is no way to modify the private members _x and _y, and you can only get their values through the accessors. It's nice to have truly private members and it's actually useful to build security in mashup scenarios where pieces of code come from untrusted sources. It's extremely tricky to get right but it can be done.

Now in most other situations, it's not really of paramount importance that your private variables remain untouchable. Actually, in .NET, private members are accessible through reflection. You need reflection permissions, but they sure are accessible. Furthermore, there is one circumstance where you do want your private variables very accessible, and that is when debugging. Inspecting private fields is one of the main things you want to be able to do from a debugger, especially when property accessors are not being automatically evaluated by the tool.

So even if it seemed like a good idea to get really private variables, well it really isn't (except when you really, really need them).

But there's another problem with closure-based classes and that's performance. For every instance you create, all the methods have to be recreated. This means that you pay a higher price to object creation and that the working set gets bigger with each instance.

Let's look at prototype-based classes and see the pros and cons of that approach. Here's the same point structure built using prototypes:

function Point(x, y) {
  this._x = x;
  this._y = y;
}
Point.prototype.get_x = function() {
  return this._x;
}
Point.prototype.get_y = function() {
  return this._y;
}

In this case, _x and _y are only private by convention. Nothing prevents anyone from tampering with them. In most cases though, that's fine, and you actually want that to be possible from the debugger.

Performance-wise, prototypes are also better in almost every situation. First, they minimize the working set: here, there's only one copy of the get_x and get_y functions for all Point instances. What differentiates the instances is only what this points to. In terms of speed, creating instances is faster, but calling methods is just a little slower because of the need to lookup the method on the prototype chain.

So far, Atlas has been using closures. Starting with the next version, all of our classes will be using prototypes. Closures are still supported but prototypes are the recommended pattern.

In part 2, I'll show how to easily transition a closure-based Atlas class library to prototypes, with clear do's and don't's.

Read on: http://weblogs.asp.net/bleroy/archive/2006/10/14/From-closures-to-prototypes_2C00_-part-2.aspx

Careful with that prototype, Eugene

Here's one that could cost you some long and puzzling debugging sessions.

What's the difference between

Foo.Bar = function() {
  this.number = 0;
  this.stuff = {};
}
Foo.Bar.prototype.toString = function() {
  return "Bar #" + this.number + (this.stuff.id || "");
}
and
Foo.Bar = function() {}
Foo.Bar.prototype.number = 0;
Foo.Bar.prototype.stuff = {};
Foo.Bar.prototype.toString = function() {
  return "Bar #" + this.number + (this.stuff.id || "");
}
Well, it becomes obvious when you try the following:
var a = new Foo.Bar();
var b = new Foo.Bar();
a.number = 1;
a.stuff.id = "a";
b.number = 2;
b.stuff.id = "b";
alert(a.toString());
alert(b.toString());

In the first case, you'll get "Bar #1 a" and "Bar #2 b". In the second "Bar #1 b" and "Bar #2 b". The reason is that both instances of Foo.Bar have the same prototype, so they both share the same object as their "stuff" field. If you set it on any instance, it affects all of them. In the first case, a new object is created from each instance's constructor.

Using the prototype to keep the cost of constructing instances as low as possible is a good idea in general but as most powerful concepts it must be handled with care. In the next article, I'll detail the difference between the closure style of JavaScript type definition and the prototype style. This is one of the caveats to keep in mind when going the prototype way.

Now, this could very well be taken advantage of by defining a "static" blob on the prototype to simulate the concept of fields shared between instances. That would kinda work but it would be a little weird to have statics hanging off a field on instances and it would be easy to overwrite this static blob off any instance. But the best argument against that is that defining statics as members of types (i.e. constructor functions) works much better and is more natural. The only problem with the latter method is statics are hard to differentiate from instance members of the type Function.

More Posts