Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm working on a DOM-shim project.

For a small subset of the DOM4 specification (Actually a subset of the Node interface) I already have 400+ lines of functions.

I presume keeping this up will become a maintenance nightmare, fast.

How do I organize large bags of functions like that?

As a seperate issue I'm using a build script to concatenate my source library files together just like jQuery does.

Currently my build file hard codes the names of every file in a specific order. This seems ugly and hard coupled.

When creating a single javascript library from multiple smaller files by build process, what's the cleanest way to this?

What is a good way to share code and be modular without placing everything in a top level file?

share|improve this question

1 Answer

If I'm understanding what you're asking, you're asking how to better organize the files and their contents so that they can be combined into a single file for distribution? This is a great question, and one faced by almost every large JS project.

The option I use most is a custom Makefile or Ant build.xml to replace file contents, concate, and then minimize files. Some good examples of this approach can be seen in the html5boilerplate and jQuery projects.

The disadvantage of this approach is that it always includes all of your JavaScript in every page. If you've only got a small amount of JavaScript this isn't a problem but it can waste bandwidth if you've got items you're not going to use on every page.

In this case, you can modify your Makefile to construct multiple, page specific JavaScript files, then load them up seperately on each page. If you'd like to load them "on-demand" as they're used on your pages you should consider using a dynamic script loader:

Another trick I've used to help organize my final JavaScript is using a JavaScript namespace function to collect related JavaScript into objects (called packages) that are nested in the JavaScript namespace. For example, I'm writing a library called htmlerizr, then all the code for my library would exist as properties of the htmlerizr object. Inside that object we organize the parts of the library into nested objects. So all my parsing functions would exist as properties under htmlerizr.parsers. These package objects can easily be created using a simple namespace function which retrieves an object if it already exists, or returns it if it doesn't.

// ### namespace()
//
// This is the main tool used to organize large JavaScript code bases.
//
// Given the name of a namespace, return a reference to a namespace in the
// global context.
//
// If supplied, an optional callback function is invoked which receives an
// exports object as the first parameter. Any values added to this object are
// merged into the namespace overriding existing values.
//
// If the namespace doesn't exist it is created, otherwise the existing
// namespace is returned instead.
//
// This function accepts the following options:
//
//   * seperator - the character which seperates the namespace components (default is ".")
//   * context - the context in which to create this namespace (default is window)
//
// The names of namespaces are seperated by a peried (e.g. "htmlerizr.parser")
//
// Examples:
//
//     // Define a new namespace
//     namespace("htmlerizr.util", function(exports) {
//         var hidden_var = "For my eyes only";
//
//         function part_of_my_implementation(arg) {
//           var i_am_not_shared;
//         }
//
//         exports.forTheWorld = function() {
//             log("Call me with htmlerizr.util.forTheWorld()");
//         };
//     });
//
//     // Alias the utils namespace
//     var util    = namespace("htmlerizr.util");
//
//     // Add more functions to htmlerizr.util
//     namespace("htmlerizr.util", function(exports) {
//         exports.anotherFunction = function() {
//             log("Call me with htmlerizr.util.anotherFunction()");
//         };
//     });
namespace = function(namespace, callback, options) {
  var settings, parts, i, currentNs, lastNs;

  settings = $.extend({
    seperator: ".",
    context: window
  }, options);
  parts   = namespace.split(settings.seperator);
  currentNs = settings.context;

  for(i = 0; i < parts.length; i++) {
    currentNs = currentNs[parts[i]] = currentNs[parts[i]] || {};
  }

  if (callback !== undefined) {
    callback.call(this, currentNs);
  }

  return currentNs;
};

There are the tricks I've used to organize my projects. Hope they help!

share|improve this answer
I currenlty use such a build script and I use namespacing. I dont think asynchronous loaders are worth it in this case. – Raynos Oct 28 '11 at 15:13
Is there something more specific you're looking for? Can you be clearer what you mean when you say "the cleanest way to do this"? – Mark B Oct 28 '11 at 21:31
I'll try to revise my question based on the current state of the project. I've added two specific questions. – Raynos Oct 28 '11 at 21:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.