You are on page 1of 2



Modules are reusable software components that form the building blocks of applica‐
tions. Modularity satisfies some very important design goals, perhaps the most impor‐
tant of which is simplicity.
When you design an application with a lot of interdependencies between different parts,
it becomes more difficult to fully understand the impact of your changes across the
whole system.
If you design parts of a system to a modular interface contract instead, you can safely
make changes without having a deep understanding of all of the related modules.
Another important goal of modularity is the ability to reuse your module in other ap‐
plications. Well-designed modules built on similar frameworks should be easy to trans‐
plant into new applications with few (if any) changes. By defining a standard interface
for application extensions and then building your functionality on top of that interface,
you’ll go a long way toward building an application that is easy to extend and maintain
and easy to reassemble into different forms in the future.
JavaScript modules are encapsulated, meaning that they keep implementation details
private and expose a public API. That way, you can change how a module behaves under
the hood without changing code that relies on it. Encapsulation also provides protec‐
tion, meaning that it prevents outside code from interfering with the functionality of
the module.
There are several ways to define modules in JavaScript. The most popular and common
are the module pattern, CommonJS modules (the inspiration for Node modules), and
AMD (Asynchronous Module Definition).

Principles of Modularity
You can think of modules as small, independent applications that are fully functional
and fully testable in their own right. Keep them as small and simple as possible to do
the job that they are designed to do.
Modules should be:
Each module should have a very specific function. The module’s parts should be
integral to solving the single problem that the module exists to solve. The public
API should be simple and clean.
Modules should know as little as possible about other modules. Instead of calling
other modules directly, they should communicate through mediators, such as a
central event-handling system or command object.
It should be fairly simple to test and use modules in isolation from other modules.
It is common to compare them to components in an entertainment system. You
could have a disc player, radio receiver, TV, amplifier, and speakers, all of which can
operate independently. If you remove the disc player, the rest of the components
continue to function.
It should be possible to fit various modules together in different ways to build a
different version of the same software or an entirely different application.
It should be possible to completely substitute one module with another, as long is
it supplies the same interface. The rest of the application should not be adversely
impacted by the change. The substitute module doesn’t have to perform the same
function. For example, you might want to substitute a data module that uses REST
endpoints as its data source with one that uses a local storage database.

The Open Closed Principle states that a module interface should be

open to extension but closed to modification. Changing an interface
that a lot of software relies on can be a daunting task. It’s best if you
can avoid making changes to an existing interface once it has been
established. However, software should evolve, and as it does, it should
be easy to extend existing interfaces with new functionality.

72 | Chapter 4: Modules