topics: functional programming, concurrency, web-development, REST, dynamic languages

Tuesday, March 18, 2008

Extending to support inheritance for domain types

As I've previously blogged about, the JavaScript framework ExtJS provides an excellent support for developing models in Controller-Model-View architectures in web-browser client applications. One of the tools Ext provides is the function using this one can easily create constructor functions for domain concepts. For example, in our room-booking application, TriBook, we defined a Reservation type concisely like this:

com.trifork.tribook.model.Reservation =[
{name: 'start_at', type:'date', dateFormat:'d/m/Y-H:i'},
{name: 'end_at', type:'date', dateFormat:'d/m/Y-H:i'},
{name: 'room'}

That is: a Reservation object has 'start_at' and 'end_at' Date properties as well as a 'room' property (which refers to a 'Room' domain object, defined of course using

One point made in a previous article is that returns a JavaScript constructor function for the defined domain concept. This means that we can add domain logic to our domain types by augmenting their prototypes, e.g.,

Ext.apply(com.trifork.tribook.model.Reservation.prototype, {
isPreLunchReservation: function(){//just an example...
var sh = this.get('start_at').getHours(),
eh = this.get('end_at').getHours();
return 6 <= sh && eh <= 11;//must end before noon...

This is all very useful, particularly because objects are supported by a bunch of other Ext functions, as discussed previously.

However, there is no built-in support for inheritance in domain concepts. For example, suppose that we like to create a sub-type of our reservation domain type: a RecurringReservation, which one can use e.g., to reserve a room the same time each week. It would be nice to be able to write the following:

var m = com.trifork.tribook.model;
m.RecurringReservation =, [
{name:'interval', type:'string'}//can be 'daily','weekly', 'monthly' or 'yearly'
var rr = new m.RecurringReservation({
room:room_ref,//assuming room_ref refers to a m.Room object.
interval: 'weekly'

Now, the object referred to by 'rr' should have all the specified state, and all the domain logic of Reservation should be inherited, e.g., 'isPreLunchReservation' also works for RecurringReservation objects.

The following is an Ext extension that makes the above snipplet work: = function(sp,fields){
var sb = Ext.extend(sp,{}),
sb_f = sb.prototype.fields.clone(),
Field =,

for (i=0,N=fields.length; i<N; i++) {
sb_f.add(new Field(fields[i]));
sb.prototype.fields = sb_f;
return sb;

1 comment:

Anonymous said...

brilliant - i needed this record extension ... i didn't see the code at the bottom for awhile which caused me some frustration - haha - but this is exactly, exactly what i was looking for. thanks!!!!