This list is just a result of what I have learnt by writing Node.js apps and by looking at other people’s code, so it does not want to be complete nor exact. Any suggestion is greatly welcome.
And I’m pretty sure you may have already seen or used some of these patterns without even knowing it…
This is definitely one of the most popular patterns. It consists in simply requiring all the modules from a directory, that’s it. Although its simplicity it’s one of the most popular (and handy) techniques. Npm has plenty of modules implementing this pattern: require-all, require-many, require-tree, require-namespace, require-dir, require-directory, require-fu just to name a few.
Depending on the way it is used, requiring a directory can be considered a simple utility function or a sort of plugin system where the dependencies are not hardcoded into the requiring module, but are injected from the directory contents.
Example: simple usage
Example: advanced usage (improve decoupling, extensibility)
Where each module in
/routes, is a function which defines its own url route:
In this second example, you can add a new route by simply creating a new file, with no need to modify the requiring module. This is definitely more powerful, and offers better decoupling between the requiring and the required modules.
A typical example of this pattern is when an application has an object called
App (or with the same name of the application) where all the services are initialized and then attached to this big object.
App object can be then passed around to be used by other modules, in the form of function argument or
When most of the dependencies of an application are attached to this backbone object, modules using it will actually have those dependencies injected from the outside .
Now, be aware that if you use the App object pattern without providing some kind of abstraction over the loaded dependencies, you can easily end up in having an all-knowing object, hard to maintain, and that actually corresponds to the God object anti-pattern.
But fortunately there are some libraries that can help you with that, as for example Broadway, an architectural framework which implements a quite neat version of this pattern, offering a good abstraction and more control over service lifecycle.
pre hook) or after (
post hook). The peculiarity is that in Node.js it’s often used in combination with monkey-patching and that’s what makes it very powerful but also dangerous.
If you ever used Mongoose then you must have seen this pattern in action for sure, otherwise npm offers you a plethora of modules to choose from. But it doesn’t stop here, in the Node.js community Aspect Oriented Programming (AOP) is often synonym of function hooks , take a look again at npm to see what I mean. Can we really call this AOP? My answers is NO. AOP requires cross-cutting concerns applied to a pointcut, not some specific behavior manually attached to a single (or even a set) of functions. On the other hand an hypothetical Node.js AOP solution may easily exploit hooks to apply advice to a set of functions, based for example on a pointcut defined with a regular expression and by scanning all the modules/methods in search for a match.
This is the essence of Node.js, Pipelines are everywhere, under various forms, uses and purposes. Generically, a Pipeline is a series of processing units connected together, where the output of one unit is the input for the next one. In Node.js, this often means a series of functions in the form:
You might know it as middleware and when you think middleware you say Connect or Express, but the usage of this pattern goes well beyond that. Hooks for example, a popular hooks implementation (we talked about it previously) connects all the pre/post functions in a pipeline (middleware) to “give you maximum flexibility”.
Most of the time you will implement this pattern in some way by using async.waterfall or async.auto, or using a chain of promises and maybe not just as flow control, but to make some part of you application extensible.
Another Node.js popular component has the traits of a Pipeline. Of course I’m talking about the hero called streams, and what is a stream if it cannot be piped? While middleware and in general function chains are a generic solution to control flow and extensibility, streams are better suited to process flowing data in the form of bytes or objects.
We have seen how the nature of Node.js pushes the developers towards the use of some recurring patterns and techniques and we went through some of them, showing how they can effectively solve common problems, if used properly. We have seen also how different a pattern can look depending on the way it is implemented. Feel free to leave a feedback and to let me know of any other pattern I missed in this list.