What should we call a module?

Coordinator
Jul 12, 2012 at 1:01 AM

We find that we use the term "module" frequently when discussing JavaScript applications.

We were particularly influenced by the discussion of the Module Pattern in Stoyan Stefanov's JavaScript Patterns. In addition, the Asynchronous Module Definition and the proposals on modules from CommonJS have been a factor as well.

Borrowing from Stoyan, a few other patterns for relevant to our project's definition of modules are:

  • namespaces
  • private members
  • declaring dependencies

Our goals in defining "module" are:

  • to provide a means for breaking code into composable parts
  • to explicitly expose dependencies in the code

In the context of the Hilo project, our concept of a "module" should:

  • corresponds to a single file
  • use the namespace pattern to designate a logical location in the context of the app
  • explicitly reference dependencies at the head of the file
  • export a single object (this object could be a function)
  • bear a single responsibility (an admittedly ambiguous target, but something to strive for)

What is your opinion? How do you think about modules and their role in a JavaScript application?

Jul 12, 2012 at 1:46 AM

corresponds to a single file

In small and simple cases it works out fine. But a module can still be a cohesive unit of functionality when split across multiple files. Specifically, a single file should not be mandated when that single file reaches more than a few hundred lines of code. In that case, it's reasonable for the module to be defined across multiple files. the mechanics of this (same module name / namespace?) may necessitate changes such as sub-modules for separate files. but in general, i think it's a bad idea to force a single module to be in a single file.

 

I also think the term module applies to larger groupings of functionality. the "cropping" module may be built out of 6 or 8 related files, and several of those files may in themselves by modules, or more specifically sub-modules.

 

other concerns: coupling

... a bit of rambling thinking on this subject, but should be useful anyways.

coupling becomes a huge concern across modules. i don't believe code re-use is a primary concern of modularization of code, personally ( http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/ ). but re-use is often a possibility. in the scenarios where re-use is likely (re-use meaning not the originally intended use within the same app, or re-using in another app), modules and sub-modules can create a tight coupling that will cause problems. i see this in my own backbone apps a lot. one module or file that relies on another.

if a module is well encapsulated, then it makes sense to bring all of the files for that module along for the ride in the re-use scenario. if an application's or scenario's specific needs bleed in to the module, then that module is not re-usable without changes to remove the app/scenario specific code. if one module directly relies on another module, by including the use of code that the other module defines, then we're in trouble. we have two modules coupled together. higher level patterns such as a mediator, pub-sub (events), or other patterns need to be used to keep the modules clean and separated.

Jul 12, 2012 at 7:13 AM

I'm beginning to wonder if "module" is even a useful term. It's has so many definitions!

I imagine that many modern developers have a firm concept of what an object is. So how about the approach of "one object per file" instead? (Being JavaScript, this object could be a constructor function.)

Your goals for a "module" nicely map across to a SOLID object.

Jul 12, 2012 at 1:02 PM

The term "module" has such legacy connotations around it that trying to use it to describe a collection of files may create more confusion than anything else. Historiucally, it means a single file. I'm struggling to find a better term and not having much luck.

Jul 12, 2012 at 2:44 PM

I'm beginning to wonder if "module" is even a useful term. It's has so many definitions!

unfortunately true. but i think it's important that we find an appropriate use of the term. this is a very big part of the current javascript community, and it's becoming an important topic for everyone that is starting to build modern JS apps based on ECMAScript5 and moving in to "Harmony" (ES6).

on that note, i just dawned on me that the best way to define a module in our communication and documentation is to look at how the general JS community defines it, especially considering the ES6 module syntax. it would be a bad idea for us to create a definition that is in conflict with the community's definition.

 

 

how about the approach of "one object per file" instead?

i see this as an anti-pattern when declared as a rule to follow. if a single file happens to only need one object in order to fulfill it's needs, that's fine. but the approach of only one object per file will lead to code bloat (extra module definitions), file bloat (where do we draw the line between 1 object per file and 1 line of code for an object?) 

thinking about C#, when I declare an interface and that interface exposes events, I don't create a separate file for each of the events. I include the event definition in the same file as the interface that exposes it.

thinking about Backbone, when I declare a model and collection I don't create separate files for them. I put the model and collection definition in the same file because they belong together. they are directly related and don't make sense without each other. also, a model and collection definition are often 1 line of code each. it doesn't make much sense to create a new file with a new module definition, for 1 line of code. 

on the flip side of that, though, if a single file is becoming too large to understand as a whole, the code should be split out in to multiple files where it makes sense. if a collection is moving toward a hundred lines of code and it's model is moving toward a hundred lines of code, it will be easier to read and understand the code if they are in separate files.

 

Your goals for a "module" nicely map across to a SOLID object.

+1

these principles are largely the guiding principles i use in OO development (in any language). there are hundreds if not thousands of ways to use these principles of course :)

if anyone's interested in these a little more, i wrote an article on using them in C# a few years ago: http://www.code-magazine.com/article.aspx?quickid=1001061

and a good friend of mine wrote a series on SOLID in JavaScript: http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/