Design Questions

mckoss edited this page Apr 14, 2011 · 10 revisions

Some alternative design issues. Feel free to add more, or edit the Pro: and Con: sections for each.

funcs.js - inheritance pattern

Many choices for the inheritance function: derive, inherits (Closure), subclass, extends (Java), override. I started with subclass, but am leaning to change to extends.

I am also looking for a nice multiple inheritance pattern or JS. I like the MRO feature of Python. Can this be simulated efficiently in JS?

Even simpler namespace wrapper - based on CommonJS design - adopted in v3.0

While namespace 2.2 includes the exports and require symbols, we still have the somewhat redundant wrapper for a module that uses the lookup and define functions of the namespace object:

namespace.lookup('org.startpad.foo').define(function (exports, require) { ... });

Can we further simplify this wrapper so it just does one thing - serve as a wrapped for a module closure function.

namespace.module('org.startpad.foo', function (exports, require) { ... });

Since require is just an alias for the namespace.lookup function, perhaps we should remove lookup completely; is there any reason to retain a globally available lookup when you are not inside a module scope (other than backward compatability)?

Mimic the design of CommonJS Modules - adopted in v2.2

CommonJS (most notably, the node.js implementation) uses a module definition scheme using the function name require and a defined variable exports.

var external = require('external-lib');
exports = {'exportedFunction': function () {...}};

A quite similar pattern using namespace.js:

namespace.lookup('my-lib').define(function (exports) {
    var external = namespace.lookup('external-lib');
    exports = {'exportedFunction': function () {...}};
});

Except for the outer wrapper, we could achieve the goal of code compatability by passing in a second argument to the namespace closure function to define require as an alias for namespace.lookup:

namespace.lookup('my-lib').define(function (exports, require) {
    var external = require('external-lib');
    exports = {'exportedFunction': function () {...}};
});

This would seem a nice extension to allow for portability between CommonJS modules and namespace.js uses.

Should the lookup function be added to each Namespace? ... no

That way, within a namespace closure function you'd not be dependent on the name of the global namespace variable. Seems like overkill - and would over-write any use of 'lookup' as a Namespace name (a pretty common symbol).

I prefer the CommonJS Modules emulation via exports require params to the closure function.

Why not call the closure function using this instead of ns.

We could call the closure using:

closure.call(this);

instead of:

closure(this);

Then, within the closure, this would reference the Namespace itself.

Con: this will be overridden by any method call, and so the Namespace would not be accessible unless the namespace author would assign it to a local variable:

var ns = this;

Con: Currently, this points to the global scope (i.e., window). By using .call, the global scope would not be available within the namespace closure function. This could be mitigated by passing the signature:

closure.call(this, window)

Also, for CommonJS Modules comparability, exports should be the symbol fornthe current module.

Should the namespace closure function return the value of the namespace object? - no

Con: One of the benefits of creating the Namespace on behalf of the module, is that we can forward-reference the namespace and not be reliant on load order of JavaScript files. If we required, or even allowed, modules to return their own Namespace object, we would loose the forward reference benefit.

Note that modules can make as many calls to namespace.lookup that they want, and so are free to create other Namespaces dynamically, and, of course, to add any properties to their Namespace that they want.

Namespaces can't do path-relative lookups.

Is there a case where a namespace needs to access it's parent or child (or sibling) modules? There is no direct support for that - and code that implements it would have to hard code the name of it's path directly.

Con: The current method is simple and understandable. Anding relative or rooted paths could make it complex or confusing?

Con: Reference a child namespace is simple iff you know it is already loaded:

ns.child

Pro: Adding a path_root second argument and '..' support would be pretty simple:

namespace.lookup('^.sibling', ns)
or
ns.lookup('child')
Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.