Modularity

This document contains some basic advice for how to achieve modularity, then it goes into more advanced ideas as you scroll. At the bottom lie some information on arbiters.

Welcome to Italy

It here is one thing you learn quickly in programming, it is this:

It is awful to read, but it is even worse to modify or maintain.

What is Bad Code

Without rehashing the entire internet: tightly coupled code is bad code. Because

What is Good Code

What it is not: Bad Code

If tightly coupled code is bad code, then good code is loosely coupled. A ⇒ B ∴ ¬B ⇒ ¬A.

In other words, if you factor out your behaviour into small separate units of behaviour, you will have gained maintainability and readibility properties for free, and your code will inevitably have less unknown side-effects, leading to more secure code as well. It does, however, take certain disipline to constantly police your files for multiple types of behaviour.

You may shrug and say, well, I'm only going to write this once anyway..

..and you will be right. You will write it once and likely wish you wrote it zero times.

In my opinion, the biggest mistake you can make as a learning programmer is to not bothering to factor out behaviour as early as possible.

Best Practices

modul8 provides the means to separate your code into different files effectively, but how do you as a developer split up your behaviour?

One of the hardest areas to modularize web applications is the client application domain. If you are using jQuery, you should be particularly familiar with this. $ selector calls all around, DOM insertion & manipulation code in random places, identical behaviour existing for each URL. If this is a problem for you, read on.

Decouping MVC code

If you have tried the one size fits all approach to modularity and try to cram your project into a MVC/MVVM structure, you may have had success, or you might have hated it. At any rate, here is some general ideas to consider if you are currently using or planning to use an MVC framework.

Independent entry controller

Controllers

Models

Extras

DOM Decoupling

This section is very relevant if you are just using jQuery, or if you are trying to roll your own application structure rather than using MVC.

The general jQuery advice is that you think about the behaviour you are defining. Here are 4 general rules to go on for certain behaviour:

This way if something breaks, you should be able to narrow down the problem to a UI error (code or style), a signaling error, or a calculation error. ⇒ Debugging becomes up to 4 times easier.

General Modularity

modul8 just tries to facilitate the building of maintainable code. To actually do so, you need to always stay vigilant and remember to:

Decouple your code this way and you will save yourself the trouble of later having to learn from your mistakes the hard way.

Going Further

Domains or Node Modules?

Say you have factored out a piece of behaviour from your client side app. Where do you put it? Do you put it

This are increasingly flexible depending on what you want to do. If you want to only use it on the client, you should keep it in the client root so that it is immediately obvious to anyone reading your code where it works.

If you want to use it on the server, you have to use one of the other approaches. A shared domain is great if you have completely server and client agnostic code. This is what extra domains were designed for. One of the key reasons domains were pushed by modul8 is that having a 'shared' folder next to your 'client' and 'server' folders screams to the reader that this code should work anywhere and must be treated with respect. This is good.

Sometimes however, you need extra npm functionality on either end. This is possible to achieve, but only if it is itself a node module. A node module can be required on the client if it sufficiently server agnostic. The downside to placing your code in here is that it gives no indication to the people reading your code that it will work on the client. On the other hand, it might be easier to reuse across projects when things are checked into npm. Use with caution, but it's worth taking advantage of.

Killing Globals

Global variable are evil, and should be kept to a minimum. We know this, and this is were a require system really shines, but you are generally going to depend on a few global variables. Not all libraries are CommonJS compliant, and having jQuery plugins showing up in your dependency tree under every branch that requires jQuery might just make things more confusing than to load them classically.

Besides, you may want to load it in from a separate CDN anyway.

Even in such an environment, it is possible rid yourself of the global $ and jQuery symbols without breaking everything.

We will demonstrate such a solution. Begin by constructing a jQuery.js file on your application domain containing:

module.exports = window.jQuery;
delete window.jQuery;
delete window.$

With this you can put var $ = require('jQuery') so everything will be explicitly defined on the application domain. You've also deleted the global shortcuts so that you will know when you forgot to require. Finally, jQuery (but none of its dependencies) show up in the dependency tree - so you will quickly identify what code is actually DOM dependent , and what isn't or shouldn't be. Clearly this is advantageous.

Having found this pattern very useful, but also noticing how repeating this pattern on several libraries pollutes our application code folder with meaningless files, a modul8 extension was created early on to allow automatic creation of these arbiters in the internal module system by using the arbiters() call.

This example could be automated by chaining on arbiters().add('jQuery', ['jQuery', '$']). See the API docs for more details.

DOM Dependence

Note that modul8 only allows one domain to be DOM dependent (the application domain), and from the start you are likely going to have require('jQuery') or similar in many places there.

However, if you just find some areas that do not use it, and as a result move logic to an environment agnostic domain, then it this is a great success. Your jQuery dependent code is diminished, so the more tightly coupled code of your application is smaller.

If you can efficiently separate code on the domain level, try to keep above advice in mind; always aim to factor out behavior into small loosely coupled modules. If you can do this then you are already well on your way to resolving spaghetti hell. The rest is mostly getting the correct signaling model for your events to your controllers/controller style entities.

Good luck. Hopefully this has been useful on some level : )