My new job is to write component-oriented JavaScript with Google Closure library. I adore events, components, services and modules. But the work is super-harsh because of the need to write code cluttered with namespaces. Following code is typical:
goog.provide(com.bin.slash.dot.closure.widget.SuperForm);
goog.require(com.bin.slash.dot.closure.widget.Avatar);
// ... ten require calls more...
com.bin.slash.dot.closure.widget.SuperForm = function() {
goog.base(this);
this._internal = new com.bin.slash.dot.closure.widget.Avatar(
com.bin.slash.dot.closure.widget.Avatar.SRC_PATH);
};
And I can't believe this is true. I am not afraid to type all of this, but I just feel that logic dissolved and cluttered in this symbol hell. It is very difficult to scan, hence it takes more time to understand what'is going on. My boss said, that it is discouraged to write shortcuts like:
var SF = com.bin.slash.dot.closure.widget.SuperForm = function(){};
Because all of them will be bound to the global namespace (window) after compilation, so they can interfere with something else.
The question is how to avoid this symbol hell?
Update: I have made an improvement into my developer process, which solves the symbol hell. Now I write sweetened JavaScript, that then automatically compiled by Grunt with sweet.js macros:
// For each file I define three macros which are replaced
// in the compile time with hell of a long paths.
macro dir { rule { $x } => { my.very.very.long.namespace $x } }
macro class { rule { $x } => { dir.NameOfMyClass $x } }
macro proto { rule { $x } => { class.prototype $x } }
dir.NameOfMyClass = function() {}; // yields: my.very.very.long.namespaceNameOfMyClass = function() {};
class.CONSTANT = "I don't know why we write constants into classes, not prototypes"; // yields: my.very.very.long.namespaceNameOfMyClass.CONSTANT = ...;
proto.method1 = function() {}; // yields my.very.very.long.namespaceNameOfMyClass.prototype.method1 = function(){};
All of the noise created by macro compiler is removed by excellent shelljs.