Last time I alluded to the deepened relationship between classes and namespaces in ZJS v3. I want to expand a bit on that note because of the significance of scoped lookup. Without scoped lookup, there were many compromises when writing code. Often I would be writing a class hierarchy with a base class and one or more derived classes collected together. This required annoying hoop jumping to complete one call to $namespace to get the base class registered and then make another call to add the derived class. Of course, this had to be repeated once for each derived class. For example:
$namespace(“foo.bar”,
{
Base : $class(
{
})
});
$namespace(foo.bar,
{
Derived : $class(foo.bar.Base
{
})
});
Also, when defining the derived class I had to specify the full name of its base even though it was in the same namespace. It got the job done, but it was awkward. Granted, JavaScript has different notions of scope compared to other languages, so while these deficiencies were understandable, they were, nonetheless, counter-intuitive at times (especially for new comers).
From the very beginning of ZJS I decided that namespace population should be done intelligently. The primary reason was to help detect errors and avoid overwriting members of the namespace. In later versions, I added ways to express the desire to overwrite namespace members in a controlled way as well as adding members conditionally. In fact, the overridding feature even has the ability to use $super to call the overridden method. As it turns out, the ability to conditionally override a namespace method can be quite handy when dealing with browser differences.
Other libraries don't provide a method quite like $namespace. For example, in ExtJS, the Ext.namespace method simply creates the namespace and does not populate it. The approach taken by ExtJS is perhaps the closest to ZJS, though I think this:
Ext.namespace(“foo.bar”);
foo.bar.Base = Ext.extend(Object,
{
...
});
foo.bar.Derived = Ext.extend(foo.bar.Base,
{
...
});
Is decidedly less pleasing. I suppose one could always use a bulk update method:
Ext.namespace(“foo.bar”);
Ext.apply(foo.bar,
{
Base : Ext.extend(Object,
{
...
})
});
Ext.apply(foo.bar,
{
Derived : Ext.extend(foo.bar.Base,
{
...
})
});
This looks more like the ZJS version but has some distinct draw backs. For starters, it still does not look declarative: Ext.apply is clearly an imperative statement. It is also a tad more verbose because “foo.bar” must be repeated. Finally, and more importantly, Ext.apply will blindly overwrite things already present in the namespace.
By encapsulating the tasks of namespace creation and namespace population, the $namespace design has enabled the addition of several new and more flexible techniques for populating namespace that flow very naturally from the original definition. I already have some ideas on what other features might be useful in $namespace and I have every confidence that they can be added with minimal impact.
No comments:
Post a Comment