Medryx Observations

June 9, 2008

A Javascript Object Model and Lazy Initialization

Filed under: dojo, javascript, oop — Tags: , , , , — maulin @ 9:06 pm

I’ve been thinking a lot about javascript client-side object models lately. I use dojo for my javascript oop tools, so creating classes, and inheritance is not really the problem. The problem is figuring out how to make as transparent as possible a rich relational object model. Then to figure how to do automatic dirty checking and updating.

The needs of a client side object model seem to be slightly different than those on the server. And obviously the client is more resource constrained. So we really only want to get the information we absolutely need for the client to run. But on the other hand, creating a single set of objects that can be used anywhere in our application, would obviously also be of benefit. So how to solve this?

Its all a question of optimization versus lazy-loading. If we use sparsely populated objects, and then lazy load the remaining properties on demand, then perhaps we will have the solution. We will be able to create a single object model, and use it reliably on every page of the application. Then as a performance optimization later — we can make the “laziness” disappear by populating the object less sparsely, or targeting which parts of the object model are loaded intially, and which are loaded lazy.

But if we want to create a system where we are always interacting with an object in the same way, and letting the performance optimizations occur in the background, then we need to define how exactly we are going to interact with the object.

So lets start walking through an example. Consider a Person object:

dojo.declare("medryx.model.Person", null, {
  firstName:null,
  middleName:null,
  lastName:null,
  roles:null
});

Now first things first. There is no way I can think of that we are going to be able to support direct property access of these properties and have any ability to instrument our entity to take care of performance optimization, dirty checking, and so-forth in the background. And since support for javascript property getters and setters is sparse to say the least, I think right off the bat, we are going to be left with using get and set methods for properties, ala javabeans. Don’t worry though, I am not saying you will need to necessarily write all those getters and setters. I’m just saying to access properties reliably, you will need to use them. Javascript is such a flexible language that we can handle creating these getters and setters automagically.

My standard model for instantiating an object is to pass in an associative array of properties and initialize each of the properties automatically. We could use our constructor that initializes the properties also create the getters and setters without to much additional effort. We could event handle “private” properties that do not need getters and setters. If we put this in a base class for all of our entities, we would have:

dojo.declare("medryx.model.Entity", null, {
constructor:function() {
  if (arguments[0]) { //mixin kwArguments if present, which is only valid argument to constructor of an Entity
    dojo.mixin(this, arguments[0]);  
  }
  //setup getters
  for (var key in this){
    if (key[0] !== "_") { //ignore underscore-prefixed properties
      if (!dojo.isFunction(this[key])) { //ignore functions
        this.setupGetter(key);
        this.setupSetter(key);
      }
    }
  }
},
setupSetter:function(key) {
  var setterName = "set" + medryx.util.StringUtils.capFirst(key);
  if (!dojo.isFunction(this[setterName])) { //don't use an auto-getter if a getter is already defined (allows override)
    //assume this is a property and needs a setter
    this[setterName] = dojo.hitch(this, "set", key);
  }
},
setupGetter:function(key) {
  var getterName = "get" + medryx.util.StringUtils.capFirst(key);
  if (!dojo.isFunction(this[getterName])) { //don't use an auto-getter if a getter is already defined (allows override)
    //assume this is a property and needs a setter
    this[getterName] = dojo.hitch(this, "get", key);
  }
},
get:function(property) {
  return this[property];
},
set:function(property, value) {
  this[property] = value;
}
});

and then we change person to inherit from Entity:

 
dojo.declare("medryx.model.Person", medryx.model.Entity, {
  id:null,
  firstName:null,
  middleName:null,
  lastName:null,
  roles:null
});

A quick walk-through of Entity shows that it iterates through all the properties that exist on the entity that do not start with a “_”. For each of these it creates a getter and a setter. It also mixes in a the properties from the initialization argument. Notice also that if a getter already exists, then the default getter is not used. So if you had some business logic you wanted to put into a getter or setter of your own, you
could simply create your own getProperty() method and it would not be over-ridden.

So our first cut is done. Let’s see how it works:

  Person person = new medryx.model.Person({firstName:"Maulin", roles:["super-user", "dev-user"]);
  div.innerHTML = "Hello " + person.getFirstName() + 
    "!" + " I see you have the following roles: " +
    person.getRoles().join(", ") + ".";

Simple enough. So how has this helped us? Well, it hasn’t. Yet. But now lets say that istead of explicitly instantiating the person with values, that we were loading a person via JSON in an ajax call to the server. Something like:

var deferred = loadPeople();
var people;
deferred.addCallback(function(peopleProperties) {
  people = dojo.map(peopleProperties, function(personProperties) {
    return new medryx.model.Person(personProperties);
  });
});

Cool. With very little work, I now have locally cached “people” store that I could easily build some query, sort, and filter functions for. (I’ll talk about that in a later article).

So now lets get back to the idea of lazy loading. Lazy loading can operate in two paradigms — synchronous and asyncrhronous. The advantage of synchronous is that is a very comfortable programming model. You really don’t change anything other than Entity, and you have lazy loading without changing any application code.

As an example, lets say that our call to loadPeople() above return an array of associative arrays that had firstName, middleName, and lastName for each person. But lets say roles was not sent down from the server. Now when we make a call to getRoles(), we get null, which is obviously not what we want. So somehow, getRoles() needs to know that its dealing with a lazy property.

One way would be to say that if a property === null, then try to load it lazily before returning from the getter. But what if the value is supposed to be null? Okay, then how about if we create “fake” value for any property that has the ability to be lazy loaded? Then the system could check if the property has been initialized or not, and if not, it can perform a lazy load.

So lets change our Person class a bit:

dojo.declare("medryx.model.Person", medryx.model.Entity, {
  id:null,
  firstName:null,
  middleName:null,
  lastName:null,
  roles:medyrx.model.Entity.LAZY
});

now that we have marked roles as LAZY, lets change our Entity to account for it:

setupGetter:function(key) {
  var getterName = "get" + medryx.util.StringUtils.capFirst(key);
  if (!dojo.isFunction(this[getterName])) { //don't use an auto-getter if a getter is already defined (allows override)
    //assume this is a property and needs a getter
    //check if this property is lazy
    var isLazy = (this[key] === medryx.model.Entity.LAZY); 
        //note that if this property was already initialized by the mixin in the constructor, that it would no longer be lazy
     if (!isLazy) {
        this[getterName] = dojo.hitch(this, "get", key); //default behavior
     } else {
       if (!dojo.isFunction(this.lazyLoadProperty)) {
        throw new Error("Entities with lazy properties MUST implement lazyLoadProperties");
       }
       this[getterName] = dojo.hitch(this, "getLazy", key, false);
     }
  }
},
getLazy:function(property) {
  if (this[property] === medryx.model.Entity.LAZY) {
    this.lazyLoadProperty(property); //a SYNCHRONOUS CALL that when it returns will have initialzed the property
  }
  return this[property];
}

So this code will check if a property is lazy. If it is, it will shunt the getter over to getLazy(). getLazy() will check if the property has been initialized, and if it has not, then it will ask the subclass to initialize it. Since this would be a synchronous call, the end result would be that a call the getRoles() would return the roles, just as it did before.

Finally, for completeness, lets look at the person object one last time:

dojo.declare("medryx.model.Person", medryx.model.Entity, {
  id:null,
  firstName:null,
  middleName:null,
  lastName:null,
  roles:medyrx.model.Entity.LAZY,
 
  //private:
  _allProperties:null,
 
  lazyLoadProperty(property) {
    if (!this._allProperties) {
      !this._allProperties = medryx.dao.loadCompletePerson(this.id); //SYNCHRONOUSLY laod all the properties for this person
    }
    this[property] = this._allProperties[property];
  }
});

While this implementation works fairly well for simple unininitialized properties, we now need to consider how we would handle related objects. For example, lets give a person an account object.

dojo.declare("medryx.model.Person", medryx.model.Entity, {
  id:null,
  firstName:null,
  middleName:null,
  lastName:null,
  roles:medyrx.model.Entity.LAZY,
  account:null,
 
  //private:
  _allProperties:null,
 
  lazyLoadProperty(property) {
    if (!this._allProperties) {
      !this._allProperties = medryx.dao.loadCompletePerson(this.id); //SYNCHRONOUSLY laod all the properties for this person
    }
    this[property] = this._allProperties[property];
  }
});

When we are initializing the person, we will only get an accountId from the server. We could add some custom work into the Person constructor to instantiate the team:

dojo.declare("medryx.model.Person", medryx.model.Entity, {
  id:null,
  firstName:null,
  middleName:null,
  lastName:null,
  roles:medyrx.model.Entity.LAZY,
  account:null,
 
  //private:
  _allProperties:null,
 
  //constructor:
  constructor:function(args) {
    if (args && args.accountId) {
      this.account = new medryx.model.Account({id:args.accountId, person:this});
    }
  }
 
  lazyLoadProperty(property) {
    if (!this._allProperties) {
      !this._allProperties = medryx.dao.loadCompletePerson(this.id); //SYNCHRONOUSLY laod all the properties for this person
    }
    this[property] = this._allProperties[property];
  }
});

And if account looks like:

dojo.declare("medryx.model.Account", medryx.model.Entity, {
  id:null,
  person:null,
  lastLogin:medryx.model.Entity.LAZY,
 
  lazyLoadProperty(property) {
    //to be implemented with a SYNCHRONOUS loader
  }
});

Then if I want to get the lastLogin I could write:

div.innerHTML = person.getAccount().getLastLogin();

and everything would *just work*! But the devil is always in the details. If you use this technique, you really need to think about how much data to supply to your objects in advance with enough data so that these lazy initializations are kept to a minimum. Synchronous calls to the server are by definition a bad thing.

Or alternatively, we can change our design to a slightly more complicated one, that handles lazy initialization more gracefully with ansynchronous calls. That will be the topic of my next post.

Simplified Dojo D.O.H. Testing

Filed under: dojo, javascript, oop, unit testing — Tags: , , , , , , — maulin @ 7:19 am

In my last post, I talked about how to use Dojo’s DOH for unit testing. But the more I wrote about it and used it, the more I realized that there were a couple of things that made it difficult for me to wrap my head around.

First, setUp and tearDown were not similar to their counterparts in other unit-testing frameworks, such as JUnit.

Secondly, the whole model for programming an asynchronous test seemed a bit confusing.

So I have come up with what seems to me to be a ridiculously simple solution — a custom “test fixture”.

As you recall, when registering a set of tests, you pass the name of the set followed by an array of test methods or test fixtures. The methods are simple function calls. The test fixture had the following properties:

  1. name
  2. runTest
  3. timeout
  4. setUp
  5. tearDown

In all the examples I found, this was declared as an associative array, setting each of these properties.

So a typical test looked like:

doh.register("some.test.package", [
function testOne() {
},
{
	name:"test2",
	setUp:function() {
		doSomeSetup();
	},
	tearDown:function() {
		doSomeTearDown();
	},
	runTest:function() {
		doh.assertTrue(doSomethingTrue());
	}
},
{
	name:"test3",
	setUp:function() {
		doSomeSetup();
	},
	tearDown:function() {
		doSomeTearDown();
	},
	runTest:function() {
		doh.assertTrue(doSomethingElseTrue());
	}
}
]);

But what if instead we write a class that implements all the above properties? Then we could subclass that class for a particular set of tests that shared a setUp/tearDown series. So in my first cut, I wrote a simple TestFixture class that looks like this:

dojo.declare("medryx.util.test.TestFixture", null, {
	constructor:function(testName, test) {
		this.name = testName;
		this.runTest = test;
	}
});

Okay, so its not rocket science. But already I feel like it cleaned up my tests substantially. Because now I have:

dojo.declare("some.test.fixture", medryx.util.test.TestFixture, {
	setUp:function() {
		doSomeSetup();
	},
	tearDown:function() {
		doSomeTearDown();
	}
});
 
doh.register("some.test.package", [
function testOne() {
},
new some.test.fixture("test2", function() {
	doh.assertTrue(doSomethingTrue());
}),
new some.test.fixture("test3", function() {
	doh.assertTrue(doSomethingElseTrue());
})
]);

Well that’s a start. But that got me thinking. Could I use this to simplify asynchronous tests?

As I discussed in my previous post, there is essentially a template for doing asynchronous testing:

  1. Create a doh.Deferred
  2. Do your deferred thing
  3. Attach the doh.Deferred.getTestCallback(), instantiated with your own assertions, to you deferred thing’s callback/errback
  4. Return the doh.Deferred

So I wrote a new and improved fixture:

/**
 * Use this test fixture for asynchronous tests.
 * 
 * @param {Object} testName
 * @param {Object} asyncTest: a method that ALWAYS returns a Deferred (dojo or doh)
 * @param {Object} assertionsCallback: a method that you will use to test your assetions once your defered is done
 */
dojo.declare("medryx.util.test.AsyncTestFixture", null, {
    constructor:function(testName, asyncTest, assertionsCallback) {
        this.name = testName;
        this.asyncTest = asyncTest;
		this.assertionsCallback = assertionsCallback;
    },
	runTest:function() {
		var d = new doh.Deferred();
		var actualDeferred = this.asyncTest();
		actualDeferred.addBoth(d.getTestCallback(dojo.hitch(this, "assertionsCallback")));
		return d;
	}
});

So now my asynchronous tests derive from this AsyncTextFixture and are created as:

	new subclass.of.AsyncTestFixture("testName",  function() {
		var def = doSomethingDeferred();
		return def;
	}, function(result) {
		doh.assertEqual("expected", result);
	});

I just think its easier to “remember” how to do aync testing with this fixture. Thoughts?

June 8, 2008

Dojo D.O.H. Unit Testing

Filed under: dojo, javascript, oop, unit testing — Tags: , , , , , — maulin @ 7:23 am

I have been spending the last few days experimenting with Dojo’s DOH for unit testing my javascript applications. While it has a relatively steep learning curve, and relatively little documentation, once you figure it out, it is actually quite simple and powerful. But it took me almost a whole day just to get up and running!

There are two great and simple articles about DOH on site pen that I found indispensible in learning DOH. The first talks about the logistics of setting up the tests and running them, and the second talks about how to do tests of asynchronous functions. There is a section of the Book of Dojo dedicated to this as well, but I found it hard to follow.

Setting up your test environment

The first trick to getting DOH running is to understand the “DOH Runner” application. This application lives in your /dojotoolkit/util/doh directory. If you launch it directly, it will run all the dojo unit tests. (This, by the way may be the most confusing part of runner.html. I’ve seen lots of posts about how people can’t figure out how to get runner working. I may work on cleaning this up to make it more intuitive for people to use without any difficult initial setup.) But you want to run your tests? To do this you provide the runner with a querystring argument called testModule that is your package with tests. For example, your url may look like:

../dojotoolkit/util/doh/runner.html?testModule=medryx.dao.tests.all

But that assumes that the module you pass in is a “sister” (i.e. at the same folder level) to dojo, dijit, and dojox. If it is not, then you will need a Dojo 1.2 implementation of runner.html and runner.js. Since that is not available yet, you will have to get a snapshot of the latest nightly build or access these files from subversion. These build in support for registerModulePath.

So lets say you have the following structure:

	/
	---/lib
	------/dojotoolkit
	---------/dojo
	---------/dijit
	---------/dojox
	---------/util
	------/mytoolkit
	---------/medryx

That means that when you call dojo.require(”medryx.something”) you want it to look at a path that dojo does not natively understand. So when loading dojo you have to configure djConfig with modulePaths or by calling dojo.registerModulePath() afer loading dojo. Well if you have this structure, and you are running dojo, then I am sure you know how to do this with dojo. The problem is that runner.html loads and tries to run your tests before you even get a chance to run any of your code. So the runner needs to know about the module paths when it is being called. The solution to this was adding registerModulePath as an option on the querystring for runner, so that now your url would look like:

../dojotoolkit/util/doh/runner.html?testModule=medryx.dao.tests.all&registerModulePath=medryx,../../medryx

So what does

medryx.dao.tests.all

look like? My general practice mirrors that of Dojo — I put a tests folder in every package.
The tests folder has the following content:

  1. tests: each group in its own file (roughly a 1:1 number of test files to classes in the package)
  2. all.js: a simple file that dojo.requires all the tests above
  3. runTests.html file which is a simple meta redirect to runner.html with the appropriate querstring arguments already set. Such as:
    <html>
        <head>
        <title>Dojox Unit Test Runner</title>
        <meta http-equiv="REFRESH" content="0;url=../../../dojotoolkit/util/doh/runner.html?testModule=medryx.dao.tests.all&registerModulePath=medryx,../../medryx"></HEAD>
        <BODY>
            Redirecting to D.O.H runner.
        </BODY>
    </HTML>
    

So now execute runTests.html, and you run all the tests in that package. Hurray! But what does a test look like?

Writing Tests with DOH

To register a set of test methods with DOH to be run, you call doh.register with the name of the test, and an array of the actual tests. The tests in the array can be in one of two forms: a simple function(), or an associative array with the following properties: name, runTest (the test method), setUp, and tearDown — similar to junit. Notice that there is no setUp or tearDown that can be written once and then called from before and after every test (as there is in junit). The setUp and tearDown methods here only apply to the one call to runTest that is contained in that fixture. You can sort of get around this by creating a setUp and tearDown method of your own, as a sparsely populated fixture, and then just fill in name and runTest. For example:

dojo.provide("medryx.dao.tests.TeamsDaoTest");
dojo.require("medryx.dao.TeamsDao");
dojo.require("doh.runner");

dojo.declare("medryx.dao.tests.TeamsDaoTest.fixture", null, {
	constructor(name, runTest) {
		this.name = name;
		this.runTest = runTest;
	}
	setUp:function() {
		//do something before every test you want to run
	},
	tearDown:function() {
		//do something after every test you want to run
	}
});

doh.register("medryx.dao.tests.AbstractDaoTest",
[
	new medryx.dao.tests.TeamsDaoTest.fixture("someTest", function(){
		//do your test
	}),
	new medryx.dao.tests.TeamsDaoTest.fixture("someTest2", function(){
		//do your test2
	})
]);

I personally think that is a more natural use of setUp and tearDown. I mean, if I can only use the setUp and tearDown once, then why whouldn’t I just put it in the runTest method?

So now you have a simple set of synchronous tests. You have a set of assertions supported in doh (though I would like to see more in the future). But everything you need is there: assertTrue, assertFalse, and assertEqual. Note that these DO NOT support a message that is displayed during failure. I think that is a problem — it makes finding the reason for your failed test more work than it has to. I would love to see them extend each of these methods to contain an optional 3rd parameter that is a message that gets displayed when there is a failure.

There is a nifty assertError method that I would like to spend a couple seconds on as well. This assertion takes and expected error (i.e. an Error object — which is another reason to always subclass Error for your own exceptions!) as its first parameter. You then pass a scope, and the name of a function with an array of args, and it will execute the method inside of a try-catch, and if it does not get your expected error, it will fail. This is a little complicated, but here is an example that makes it perhaps a little more simple to understand.

{
	name:"testOneInstance",
	instantiate:function() {
		new medryx.dao.TeamsDao();
	},
	runTest:function() {
	   doh.assertError(medryx.exceptions.SingletonException, this, "instantiate");
	}
},

This will fail if creating a new medryx.dao.TeamsDao() does not return a SingletonException.

Asynchronous Tests

DOH really comes into its own with asynchronous testing. This is certainly not intuitive at first, but after you understand the pattern, it becomes fairly easy to implement. I have actually posted some suggestions to the dojo forum about ways that asynchronous testing could be made simpler with a minimal set of modifications, so we’ll see how that goes. Until then, this is how I suggest you implement asynchronous tests. Before you begin, make sure you really understand Deferred’s!

First, you need to understand the contract you are making with DOH when you run an asynchrounous test. You “mark” a test as asynchronous by having your runTest method return an instance of doh.Deferred. Notice that is NOT dojo.Deferred. DOH has its own Deferred implementation that you must return.

When you return a doh.Deferred from your runTest method, you are agreeing to, at some point run the .callback() or the .errback() methods on the deferred you return. The

d.errback(e)

method should be called with any exceptions that occur in your test, or if your assertions fail. Otherwise, call

d.callback(true)

So to summarize:

To Make Your Test Do This Call This
Pass deferred.callback(true);
Fail deferred.errback(some new assertion error)
Fail in Error deferred.errback(error);

Notice how this is VERY different than the usual methodology for running tests in which you do something, and then make some assertions about the outcome, and the assertions themselves handle telling the test-framework whether the test passed or failed.

So an example of implementing an asynchronous test using this method would be: (crediting Dustin Machi)

doh.register("tests.DeferredExample",[
     function myDeferredTest(t){
           var dohDeferred = new doh.Deferred();
           var expectedResult = "foo";         

           var realDeferred = someAsyncFunction();

           realDeferred.addBoth(function(result){
                    if (result==expectedResult) {
                       //our test succeeded, fire the callback
                       dohDeferred.callback(true)
                    }else{
                       dohDeferred.errback(new Error("Unexpected Return: ", result));
                    }
           });

           return dohDeferred;
    },
    .... more test functions
]);

So can you even you assertions in this? Well, not quite. A failed assertion throw an error. If an error occurs in your test you must call errback. So if you surround your assertions in a try-catch block you can use them. So your new test looks like:

doh.register("tests.DeferredExample",[
     function myDeferredTest(t){
           var dohDeferred = new doh.Deferred();
           var expectedResult = "foo";         

           var realDeferred = someAsyncFunction();

           realDeferred.addBoth(function(result){
                    try{
		doh.assertEqual(result, expectedResult);

                       //our test succeeded, fire the callback
                       dohDeferred.callback(true)
                    } catch(e){
                       dohDeferred.errback(new Error("Unexpected Return: ", result));
                    }
           });

           return dohDeferred;
    },
    .... more test functions
]);

Well that is starting to feel a little more natural, but I’m still not quite satisfied. Its still a lot of glue code, and it still feels to hard to write quickly and easily and reliably. Enter the template method pattern.

doh.Deferred contains a method called getTestCallback that is a template for all of the above glue code. All you pass to getTestCallback is a function in which you perform your testing as usual, and the glue code is handled for you. So the above can be simplified to:

doh.register("tests.DeferredExample",[
     function myDeferredTest(t){
           var dohDeferred = new doh.Deferred();
           var expectedResult = "foo";         

           var realDeferred = someAsyncFunction();

           realDeferred.addBoth(dohDeferred.getTestCallback(function(result) {
		   doh.assertEqual(result, expectedResult);
	});

           return dohDeferred;
    },
    .... more test functions
]);

Now that is not too bad! Create the doh.Deferred, run your asynchronous test, and attach the doh.Deferred’s getTestCallback method (containing all of your assertions) to your asynchronous method’s callback and errback handlers. Excellent!

I hope this helps get you started on the wonderful road of javascript unit testing!

Configuration, Directories, and Builds for Javascript Web Applications (Part 2)

Filed under: dojo, javascript, oop — Tags: , , — maulin @ 12:30 am

In my first installment in this series, I described an overall file structure and configuration scheme that made it easy to develop and deploy javascript web applications. In this installment, I will describe the structure of my javascript library, how it lends itself to a loosely coupled architecture that is easily tested, and how it integrates with Dojo’s DOH unit testing system.

First lets look at the file structure:

As you can see, I have created my own package of javascript files called medryx, which I register using djConfig as I illustrated in part 1. Lets dive into some of the details of the medryx package:

  1. The first folder is called config. Anything that can change from deployment-todeployment is abstracted into various config files, that can be swapped out fairly easily. The “master” config is located in medryx/config.js. This file simply uses dojo.require() to build up the list of configuration “constants” that are available to the deployment. Other files need only add dojo.require(”medryx.config”) to get the current values of these constants.

    dojo.provide("medryx.config");
    
    dojo.require("medryx.config.base");
    dojo.require("medryx.config.rpc");
    

    A second benefit this method of declaring constants is that you can use a different set of constants for your tests, a second set for development and usability, and a third set for production. For example, my unit tests first call dojo.require(”medryx.config”), but then they explicity call dojo.require(”medryx.config.mock”), which effectively replaces the rpc related constants with the mock versions.

    Here is an example of what one of the “component” config files looks like:

    dojo.provide("medryx.config.mock");
    dojo.require("medryx.rpc.MockJsonService");
    
    (function() {
        var config = medryx.config;
       config.rpcService = medryx.rpc.MockJsonService;
       config.rpc = {
            userService: config.libUrl + "/mock/MockUserService.js",
          teamService: config.libUrl + "/mock/MockTeamService.js"
        }   
    
    })();
    

    There is a nice trick here for those who haven’t seen this kind of notation before. Notice how we define an anonymous function, and immediately call it? This allows us to avoid having to declare any global variables, or to use an extremely verbose name for every constant. We declare a local variable called “config” that points to medryx.config. Then, all the “config.*” constants, are actually “medryx.config.*”. A second benefit is that when shrinking this code, “config” will be replaced with a shorter variable, wherease if you used the full “medryx.config” no replacement could occur. (Only local variables are replaced during shrinking.)

  2. The next folder to pay attention to is the “exceptions” folder. I always use my own exceptions (that extend Error) when throwing an error! Its much easier to debug, than searching for the cause of “Error” or “TypeError”. Especially when all this code is eval’d by javascript. (Yes, I know there are workarounds for the eval problem and lack of line numbers, but believe me, custom exceptions can really save you! And they are a cinch to create. All they really consist of is a declare statement and a custom constructor:

    dojo.provide("medryx.exceptions.UnimplementedAbstractMethodException");
    
    dojo.declare("medryx.exceptions.UnimplementedAbstractMethodException", Error, {
       constructor:function(unimplementedMethod) {
          this.name = "UnimplementedAbstractMethodException: " + unimplementedMethod;
          this.message = "Subclasses must implement: " + unimplementedMethod;
       }
    });
    

  3. Finally lets exam the “layers” of my javascript. As you can see I have several packages — dao, model, rpc, and widgets. While there is some dependence between the packages, most of the packages can be tested in isolation by creating mock version of their external dependencies. So lets look more closely at the layers:

    • Model: This layer contains the entities that the application will interact with. They are typically similar to (though not identical to) their server side counterpart (or even more roughly, they correspond each to a table in a database). There can be relational dependence in the model (i.e. a Person can belong to a Team).

      Now I’ve had people tell me this is overkill for javascript. But I think that its not much more effort to build, and makes everything more extensible and more testable. For example, when first building this application, we didn’t ever really care about who the people on a team were, other than displaying their names. So a naive implementation of this might be:

      dojo.declare("medryx.model.Team", null, {
         teamName:null,
         attendingName:null,
         upperLevelName:null,
         internName:null
      });
      

      But then someone comes along and asks us to create a team that can have two interns on it. Hmmm. Well, we could change internName to:

         //...
         internNames:[]
         //...
      

      and then enter an array of intern names. But then you’ll have to remember to change every call to internName and figure out what to do with it. And then what if they tell you some teams have two attendings? Now consider if we used a more fine grained object model right from the start.

      dojo.declare("medryx.model.Person", null, {
         name:null
         role:null
      });
      dojo.declare("medryx.model.Team", null, {
         teamName:null,
         members:[] , // an array of People
         getTeamMemberByRole:function(role) {
            //to-do
         }
      });
      

      Creating a “Person” class was really simple. There are just a couple lines of code. But now consider first how easy it is to extend who can be on a team. And consider if a requirement to display the pager number for each team member comes up. Just add the field to Person, and you are done!

      The most important feature of a model entiy is its constructor, since this is how we will instantiate and populate the model in the next layer — the Dao.

    • Data Access Objects: The Dao layer is “glue code” the connects our raw server-side services to our model. It provides the application with a common mechanism to “query” and obtain instances of entities that it needs, or lists of them.

      Consider again our “Team” example. The TeamsDao provides a getAll() method that will allow for custom filtering and sorting of the list of teams, and a getById() method that will get a team with a given id.

      It is the Dao’s responsibility to query the server and to cache the Team entities for use by the client. If the team had any editable properties, it would be the Dao that would save the object back to the server via its rpc. Obviously some calls into the Dao can be synchronous, but many are not. As a rule, I always return Deferred objects from Dao methods, so my client code does not need to know when to use synchronous access and when to use asynchronous access.

      In previous implementations of this pattern, I put direct xhr requests into the dao. But this “hard-coding” of my interaction with the server proved difficult to unit test, and made my web application much more at the mercy of which server side technology we were using to get the data. Adding in the next layer — the rpc — abstracts the interaction with the server to yet another layer, making this layer easier to test. In addition, we don’t have to create mocks of any of our Dao objects. This means that as we test parts of our application that are dependent upon the Dao, we can rest assured that any bugs we find are not because of a faulty mock dao.

    • Business Objects: The Dao layer is used almost exclusively by the next layer — the service layer, sometimes called the business layer. I use business because the word service is overloaded, and could mean RpcService or Service layer. In addition to interacting with the Dao, the service layer may call upon business methods of the rpc layer.

      This is where the “business” of the application is done — enforcing security, validating data, manipulating data, deciding whether an object should be saved, etc. This is the layer that most frequently communicates with the UI layer above.

    • RPC Services: I talk about my RPC layer extensively in this post. But briefly, this is basically a set of SMD files that are used to create services that interact with the server in some way. Note that this is the ONLY way that this web application communicates with the server!

      As I said in my previous post, I look at the SMD as a “contract” with your server. As long as you both stick to your contract the rest of how you work should be completely independent of one another. There is always some negotiation that has to occur when defining the terms of the contract, but once it is established, it makes development easier for both sides, a known, reliable, and testable deliverable for both sides, and allows for parallell development with neither side blocking the other’s progress in any way.

      If the SMD definitions are the contract, then the unit tests in this layer are its enforcement. By creating a solid set of unit testing of the SMD contract, you can essentially validate (or invalidate) any server implementation of the contract. Server guys want to move from windows with M$-SQL and ASP to J2EE and MySql? Go fo it! Just make sure these tests pass when you are done!

      A small note about how I declare my SMD’s. I declare each SMD as a class (as opposed to an SMD file). This lets me use dojo.require to get the definition. Its probably just a style choice, but it seems easier to me.

    • Widgets: This is the layer that everyone seems to be focused on. But really, as long as the other layers are all working well, then this layer becomes very straightforward to implement. Need to validate some fields in a form widget? Don’t! Just delegate that work to the business layer. You know the business layer works, because it has been thoroughly unit tested.

      I make just about every piece of my web applications into a widget. I use compound widgets if needed to group smaller ones together. But I never want to see any real amount of javascript in my html page. Just markup!

      This is definitely the hardest layer to test. But, its still possible. The piece that becomes more complicated is testing the “look and feel”. This is probably in the realm of usability and acceptance testing realm than true unit testing. Tools that you could use to help could be something like Selenium. More on that in my unit-testing post.

In this article, I’ve covered the most important elements of a layered approach to javascript web applications. Creating layers allows multiple people to simultaneously develop portions of the application without impeding the progress of others, by making simple stubs or mocks of the behavior that will be expected by the surrounding layers. It allows for easier unit testing, and ultimately makes it easier to fulfill ever-changing specifications and requirements. In my next post, we’ll dive into Dojo’s DOH and talk about how we will implement this “easy” unit testing.

June 7, 2008

Javascript, OOP, and Abstract Classes

Filed under: javascript, oop — Tags: , — maulin @ 6:15 am

One thing that is clearly missing from javascript is a clear way to distinguish private and public methods within a class. Convention dictates that methods and properties beginning with an underscore are “private”, and others are “public”. And this works fairly well.

But recently, I have been building a very complicated web application, and I have really started to miss abstract classes, interfaces, and protected methods. Dojo has addressed many of these issues with its dojo.declare() syntax. With it, you can mixin an interface, or a base class when creating a new class (or more than one for that matter).

But there still isn’t any real support for abstract classes and abstract methods. As you know, abstract methods must be implemented by subclasses. In addition, there is no support for protected methods. if underscore is private, and no underscore is public, what is a protected method that should only be called or implemented by subclasses?

First, we need to decide how to indicate a method is abstract/protected. I’ve decided a reasonable approach is to prefix the method name with a $. Its unobtrusive, valid javascript, and is far prettier than “protected_” or something like that.

So now we have a way to mark methods that are required to be implemented in a subclass. For example:

dojo.declare("medryx.dao.AbstractDao", medryx.AbstractBase, {
   /**
    * abstract - the entity managed by this dao
    */
   $getEntityClass:null,
 
   /**
    *abstract - the smd of a service that is used by this dao
    */
   $getService:null
});

Notice that these abstract methods are prefixed with “$”, and assigned to null. This is key. The subclasses should implement them as methods as:

dojo.declare("medryx.dao.TeamsDao", medryx.dao.AbstractDao, {
   $getEntityClass:function() {
      return medryx.model.Team;
   },
   $getService:function() {
      return medryx.rpc.TeamService;
   }
})

Now obviusly, we could just stop there, and adhere to this convention. But errors that are borne out of not implementing these methods can be hard to find, or come out quite late… only after trying to use these methods. To address this problem I have built a base abstract class that any abstract class can inherit from (or mixin). This AbstractBase class will check the class in its constructor, and be sure all $ methods have been implemented. If they haven’t, it will throw an exception — in the constructor. Which of course means that the moment you instantiate the class, the error will occur, and will be quite descriptive of the problem. Its not quite as good as “compile-time” checking, but its closer.

Here is the code:

dojo.provide("medryx.AbstractBase");
dojo.require("medryx.exceptions.UnimplementedAbstractMethodException");
dojo.declare("medryx.AbstractBase", null, {
   constructor:function(args) {
      for (var methodName in this) {
         if (methodName.charAt(0) === '$') {
            if (!dojo.isFunction(this[methodName])) {
               throw new medryx.exceptions.UnimplementedAbstractMethodException(methodName);
            }
         }
      }
   }
});

So what are your thoughts? I think the runtime overhead of this is likely to be fairly small. But honestly, this is mostly code you need at development time. You could conceivably completely remove this constructor for production code, since presumably you have ferreted out bugs like this long before production. Heck, it could even be part of your build script!

Powered by WordPress