wiki:NamespacesModulesAndRequire

Namespaces

  • prevent naming clashes
  • adapted from  http://higher-order.blogspot.com/2008/02/designing-clientserver-web-applications.html
  • mimics naming of Java packages
  • namespace is created with
    namespace('lively.test1.test2')
    
    • creates namespaces lively, lively.test1, lively.test1.test2 which are all JavaScript objects
    • also possible is to pass in a context object, in the following namespace 'lively' must already exist
      namespace('test1.test2', lively)
      
  • namespaces can be used directly
    lively.test1.newFunction = function() ...
    
  • or via using
    using(lively.test1).run(function(theNamespace) { theNamespace.newFunction = function() ... });
    
  • for creating classes in a namespace, the namespace must be explicitly appear in the subclass method
    Object.subclass('lively.test1.NewClass', { ...});
    
    • Should we extend the subclass method, so that a namespace can be passed in as a parameter?
      using(lively.test1).run(function(theNamespace) { Object.subclass('NewClass', theNamespace, { ... }); });
      

Modules & Require

Modules should provide a simple interface for

  • categorizing source code/classes as first class objects,
  • preventing name clashes (they create namespaces),
  • dynamically loading other modules,
  • describe module dependencies,
  • finding a source code file e.g. of a class.

They are based on the assumption that a one-to-one relationship between files and module namespaces exist. Problem: this assumption is currently not enforced but Krzysztof mentioned that this would be possible with the freeze operation in ECMAScript 3.1.

The last part of a module name identifies a JavaScript source code file. The module name lively.Tests.FabrikTests would mean that in the directory ./lively/Tests exists a JavaScript file named FabrikTests. At the same time a module lively.Tests.FabrikTests.Test1 could exists. Here FabrikTests resolves to a subdirectory.

Note: Currently lively resolves to the LK base directory.

Current Usage

  • Naming conventions
    • module('lively.TileScripting') identifies TileScripting.js in the LK Base directory
    • module('lively.Tests.TileScriptingTests') identifies TileScriptingTests.js in the subdirectory Tests
    • Optionally it is also possible to write module('TileScripting.js') or module('Tests/TileScriptingTests.js') but the namespace style is recommend
  • Defining a new module with requirements:
    module('lively.Tests.TileScriptingTests').requires('lively.TileScripting', 'lively.Helper').toRun(function(thisModule) {
      // code which is dependent from TileScripting.js and Helper.js goes here
    })
    
    • the requirements are not loaded in a specific order (which might soon change)
    • thisModule is bound to lively.Tests.TileScriptingTests and can be used like theNamespace in the examples above
  • just run some code which dependents on another module, great for lazy loading of js files:
    require('lively.TileScripting').toRun(function() { lively.TileScripting.TileBox.open() })
    
    • Be careful -- code out of the toRun block shouldn't rely on code inside of the block (even if it comes after the require). Code inside a toRun block is run asynchronously.
  • Every required module must be defined!

Modules

  • created with module function
  • also creates namespace
  • module function is called with module name which can be something like
    • Tests/TileScriptingTests.js --> creates namespace lively.Tests.TileScriptingTests
    • lively.Tests.TileScriptingTests --> directly pass in namespace identifier
  • a module is a JavaScript object created with the namespace function
    • but has also arequires function

Require

  • Dynamic loading happens asynchronously, dependent code must be run after all dependencies
    • Problem: finding recursive dependencies and waiting

... More to come ...