How to structure big Node.JS modules

modulesnode.jsproject-structure

I am working on a rather big Node.JS project with several thousand lines of code. It's not a homepage, but acts more like a configurable general purpose application server. As such it brings some parts which are useful in most projects I do.

The problem is that I easily lose overview in the core modules. So I did a bit of research and came up with an interesting structure based on C++ Header/Code file structures. I want to know if this structure is good in the long run (maintainability, testability, extensibility), how it can be improved and if there is already a (better) "standard" way of doing the structuring I did not find.

The structure has three kinds of files, where xxx is the module name and yyy is the method name.

  • xxx.h.js: The "header" file, which contains the class and method declarations
  • xxx.yyy.c.js: The "code" files, which contain one method each (and possibly local helper functions)
  • index-xxx.js: The glue and main file for the module

I would like to structure all my sub-modules like this and then use a loading-mechanism to load all modules, namespace them and finally use them globally.

Here's an example:

package.json

{
    "name": "Foo",
    "version": "1.0.0",
    "description": "Does something in the core system",
    "author": "Marco Alka",
    "main": "index-foo.js"
}

// index-foo.js
'use strict';

// return class
module.exports = require('./foo.h.js');

// overwrite definitions with declarations
// this part can and most probably will be done generically by my module loader. I write it down for easier overview.
require('./src/foo.bar.c.js');
require('./src/foo.baz.c.js');

// foo.h.js
'use strict';

/**
 * Easy-to-read interface/class
 * No obstructive code in my way
 */
module.exports = class Foo {

  constructor() {}

  /**
   * Put comments here
   */
  bar() { throw 'Not Implemented'; }

  /**
   * More comments for methods
   * See how the method declarations+documentations nicely dominate the file?
   */
  baz() { throw 'Not Implemented'; }
}

// src/foo.bar.c.js
'use strict';

// include header
var h = require('../foo.h.js');

// implement method Foo::bar
h.prototype.bar = function () {

  console.log('Foo.bar');
}

// src/foo.baz.c.js
'use strict';

// include header
var h = require('../foo.h.js');

// implement method Foo::bar
h.prototype.baz = function () {

  console.log('Foo.baz');
}

Example on how to use the whole thing from within the root folder

'use strict';

// later on a module loader will be used which loads the folder as module instead of the index file directly
var F = require('./index-foo.js');

// make object
var foo = new F();

// call method
foo.bar();

Output in console: Foo.bar\n

Best Answer

I'm a newbie and I'm pretty sure this is an opinion-based answer which is really outside the scope of the board. With that, here's my practical experience:

  • There are no implicitly bad ways to structure code, so long as the structure can be described simply.
  • The only thing bad about poor code structure is lack of discipline: if you consistently follow the structure when developing, then you or anyone else editing your code should be able to discern the context quickly.
  • Even if you are the only person on your development team (which is sounds like you are), use Git or some other kind of repository with good robust explanations for what you changed and why.

It's been my experience that code structures are not usually the culprits for making things difficult to manage. It's logical architecture and documentation. If you have a good logical architecture that clearly defines modularity of functionality and you document what you've done, it will be an investment that pays off.