The Fundamentals of the Node.js Module Paradigm? - javascript

I am struggling to really get a grasp on some fundamental basics here, and I feel it is not only holding me back, but resulting in crappy code and I don't like that.
I understand the concept of breaking out functional chunks of code into separate modules, like say routes, DB models, etc, but i'm having a real tough time understanding how to properly orchestrate the interdependent functioning of all these separate modules.
Let me give a fe examples of where my struggles lie.
Example 1
My ExpressJS 'app' is setup in my main program module, just like you see in every tutorial. However I need to access the app instance in other modules as well. How do I do that? One way I learned from various tutorials is to make the entire module export a function which takes the app as a param, then do what I need in the function. But that seems to me to add a lot of complexity to things. Not only do I now have an entire module enclosed in a function, but I seem to lose the ability to actually export multiple functions, objects, or other variables out of that module.
Module as a Function
module.exports = function(app) {
blah;
};
Module without a Function
exports.func1 = function() {
}
exports.func2 = function() {
}
The latter gives me much more flexibility in my eyes, but I seem to be forced often to use the former, because I need to pass in things like the app from somewhere else.
Example 2
I am using connect-rest for my REST API. All the code for my API lives in a separate module named simply 'api'. That has been fine until recently. Now I need to access a function that is in the api module, from inside my routes module. Presently my main routes are defined before my api, so I can't exactly pass my api export into my route function. I could reverse them probably, but this is only covering up a larger issue.
In short, the issue is one of increasing interdependence
As my codebase grows, i'm finding it more and more frequent that various modules need to work with each other - it just isn't feasible to keep them all completely searate. Sometime it is possible, but it is unclean.
I feel like i'm missing some basic Node.JS (or maybe just Javascript) paradigm that is used to manage all of this.
If anyone could help me understand I would be most appreciative. I am an experienced developer in other languages such as C++ and Python if it helps to couch things in other terms.
An attempt to sum up the issue
I feel that I did not adequately communicate my intention for posting, so let me try and sum up my issue with a working problem.
server.js
var http = require('http'),
express = require('express'),
app = express();
// Bunch of stuff done with app to get it set up
var routes = require('routes.js')(app);
app.js
module.exports = function(app, express) {
var router = express.router();
// code for routes
app.use('/', router);
}
In the above example, routes are split off into their own module, but that module needs app and express objects from server.js in order to function. So, by my current understanding, the only way to get those over into routes.js is to make routes.js export one big function which you then call with the two objects you need.
However, what if I want routes.js to export multiple functions that might be used in other places? By my understanding I now can't. What if I Wanted to do:
authentication.js
var routes = require('routes');
// setup auth
routes.doSomethingFunction(auth);
I can't do that because routes is only exporting that one mega function.

Each node module is simply an object. The part of that object which is available to the outside world is the module.exports object which contains properties which can be functions or data.
The require("xxx") command gets you the exports object for that module (from a central cache or loads it from the .js file is it hasn't yet been loaded).
So, code sharing is simple. Just have each module do a require() on any other modules that it wants to share code from and have those modules make sure the shared functions are accessible via it's own exports object. This allows each module to essentially be stand-alone. It loads any other code that it needs and makes it a lot easier to reuse code. Modules are cached so doing lots of require() operations on the same module from lots of other modules is nothing more than a cache lookup and is not something to worry about.
Data sharing (such as your app object) can be accomplished in several different ways. The most common way is when you load the module to just call some sort of initialization function for the module and pass it any data that it might need. That would be the push model. Or, you can also do the pull model where a module asks another module for some piece of data.
All of this is a lot easier with the right code organization. If you start to feel like you have a spaghetti or interdependence, then perhaps you don't have the right code organization or you're just a bit too shy on just using require() to pull in everything a given module needs. Remember each module will load whatever it needs itself so you only have to worry about what you need. Load those modules and they will load what they need.
You may also want to think more in terms of objects so you put most properties on some sort of object rather than lots of loose, individually shared variables. You can then share a single object and it automatically makes all the properties of that variable available to whomever you shared it with.
As to your question about sharing the app object with another module, you can do that like this:
// in your app module
var express = require('express');
var app = express();
var otherModule = require('otherModule');
otherModule.setApp(app);
// now otherModule has the singleton `app` object that it can use
// in this case, otherModule must be initialized this way before it can do its job
In this example, I just used a single method .setApp() to set the app object. That means all the other methods are available for other access into that module.
This could have also been done with a constructor-like method:
// in your app module
var express = require('express');
var app = express();
var otherModule = require('otherModule')(app);
This works also because the constructor can then return an object with other methods on it if you want. If you want to be able to get access to otherModule from within other modules, but obviously you only want to initialize it just once and not in those other places, then you can either do this:
var otherModule = require('otherModule')();
from those other modules and have the constructor just check that if nothing is passed to it, then it is not getting the app object from this constructor call so it should just return an object with other methods. Or, you can use the first code block above that returns all the methods from the initial require(). You're totally free to decide what to return from the require(). It can be just a constructor-like function which then returns another object when it is called. It can be just an object that has methods on it or (because functions are objects that can also have properties), you can even return a constructor-like function that ALSO has methods on it (though this is a bit less standard way of doing things).
And, your constructor function can decide what to do based on what is passed to it, given it a multitude of different behaviors based on what you pass to it.

Related

A little confused about var app= express()

I've been reading through the docs but still don't quite understand why we store express() inside an app variable.
I know we can't just call methods using express().get and .post because I tried and failed, but why?
How come it doesn't work like if we would call a function from the module.exports of any file we require?
I'm just really confused lol.
express expects you to create an instance object of it and use that. A short way of answering is to say "because that's what the makers of express expect from their users."
Across your script the expectation from the developers is that your .get and .post methods are called against a common instance of express. In this way, we can say that the call to express() initializes the instance and returns an object, which you store in app.
Edit in response to your comment:
express is a function that creates a new object based off a class
express() initializes the app object and I have not yet encountered a situation where I need to know specifically how. I have no idea if it's a function or a class. This is "encapsulation", the concept in OOP where there is a clear boundary between what you, the user of a module need to know in order to use it, and what the developer of the module needs to know to keep it working.
...dependent on the method used(ex: .get), and then uses that instance to allow us to make a route that returns things such as the req and res parameters in the callback?
The initialized object implements methods, callbacks, et al (like .get as you describe.)
All of which is in the express module?
All of which is the conventional pattern for working with the express API.
What really happens when your code call var express = require('express'), it actually imports the Factory Method called createApplication (source code here).
Meanwhile, when you do express().get and express().post, you're expecting that it will return the same instance of express app object, while it's not. Your code will work if express is using Singleton pattern under the hood (resulting in the same instance being returned on every call to express()). While the Factory Method design pattern will always create a new instance.
That said, every route you add directly using express().get or express().post will always be spread across many different application instance. So basically, it will work as advertised, but not as you expected to be.

Dependency injection pattern in NodeJS

Recently, i've started dabbling into nodeJS.
Now i know that dependency injection is the go to pattern to decoupling code and keeping it all organized.
However, what do you do when you have one dependency that uses other dependencies?
For example, lets say i have a invest module which uses the database module and the user module, the user module also uses the database module.
And suppose i have an withdrawal module that uses the invest module, database module and the user module. Is it smart to define a property in the module's object and inject the other dependency into it throughout the application?
const dbc = require('./dbc');
const user = require('./user');
const invest = require('./invest');
const withdraw = require('./withdraw');
let user.dbc = dbc;
let invest.user = user;
let invest.dbc = dbc;
let withdraw.invest = invest;
let withdraw.user = user;
let withdraw.dbc = dbc;
Is this the best/smart way to go about doing this? Something feels wrong about this.
Sure, i could just inject the database module into user module and inject the user module into invest module, and the invest module into the withdrawal module. But something about this doesn't feel clean either.
If someone should show me the light, the community acccepted standard practice of going about this, that would great.
It is absolutely fine to require a module more than once. NodeJS executes the code in the module only once and remembers what the module exported.
When you require the module a second time, the module is not executed a second time (and doesn't create another database connection). Instead, the result of require('./dbc') will always by a reference to the same object that represents the database connection.
The built-in NodeJS Dependency Injection is not enough for me. Here is the reasons:
It doesn't naturally have component life cycle management, i.e Singleton, Transient, and Wrapped. Say if you wanna use a module as singleton in a context but transient in another context, you will have to deal with having two different factory methods for the module creation.
Injecting dependencies to a module body via 'require()' is not recommended as it takes central dependency management off our hands. Besides, it makes it hard to resolve Circular Dependency although this problem seldom happens.
Those motivated me to find a better DI for NodeJS apps. There're quite a few of them out there. I also wrote a lightweight DI for myself. Give it a try here if you think it helps: https://github.com/robo-creative/nodejs-robo-container
With DI's supports, I'm able to stick to declaring every module as a type, no more factory methods for them. Module life cycle will be managed by the container. Your code will look like:
var $ = require('robo-container');
// dbc should only be a type, we can restrict it to have only one instance.
$.bind('dbc').to(require('./dbc')).asSingleton();
// following statements use Property Injection
// user should be a type that may have multiple instances (transient).
$.bind('user').to(require('./user')).set({ dbc: 'dbc' });
// invest and withdraw should be types.
$.bind('invest').to(require('./invest')).set({ user: 'user', dbc: 'dbc' });
$.bind('withdraw').to(require('./withdraw')).set({ user: 'user', dbc: 'dbc', invest: 'invest' });
The binding statements above use Property Injection. If your 'withdraw' module has a constructor that accepts user, dbc and invest, you can use Constructor Injection like this:
// the withdraw module.
function WithdrawModule(user, dbc, invest) {
this.doSomething = function() {
}
}
$.bind('withdraw').to(require('./withdraw')).use('user', 'dbc', 'invest');
To create withdraw instance, call $() or $.resolve():
var withdraw = $('withdraw'); // or $.resolve('withdraw');
withdraw.doSomething();
That's it. Hope you have the answer for your questions.

Node js, split up files without having to pass dependencies around?

This may be just me lacking a 'bigger picture' so to speak, but I'm having trouble understanding why exporting modules is needed to just split up files.
I tried doing something like this:
//server.js
var app = require('koa')();
var othermodule1 = require('othermodule1')();
var othermodule2 = require('othermodule2')();
var router = require('./config/routes')();
app.use(router.routes());
//routes.js
module.exports = require('koa-router')()
.get('*', function*(next){
othermodule1.something;
})
realizing that routes.js does not have access to 'othermodule1' after calling it from serverjs. I know that there's a way to pass needed variables during the require call, but I have a lot more than just 2 modules that I would need to pass. So from my probably naive perspective, this seems somewhat unnecessarily cumbersome. Someone care to enlighten me or is there actually a way to do this that I missed?
Each node.js module is meant to be a stand-alone sharable unit. It includes everything that it needs to do its job. That's the principle behind modules.
This principle makes for a little more overhead at the start of each module to require() in everything you need in that module, but it's only done once at the server startup and all modules are cached anyway so it isn't generally a meaningful performance issue.
You can make global things by assigning to the global object, but they that often breaks modularity and definitely goes against the design spirit of independently shareable modules.
In your specific code, if routes needs access to othermodule1, then it should just require() it in as needed. That's how modules work. routes should just include the things it needs. Modules are cached so requiring it many times just gives every require() the same module handle from a cache.
This is an adjustment in thinking from other systems, but once you get use to it, you just do it and it's no big deal. Either require() in what you need (the plain shareable module method) or pass something into a module on its constructor (the push method) or create init() methods so someone can initialize you properly or call some other module to get the things you need (the pull method).

Is it ok to declare an object to be equal to itself in Javascript for the sake of refactoring a large project

I'm working on a very large javascript web app that doesn't really have a method to it. There seems to be an attempt to declare everything as part of a master object called "app". The original program existed as a single app.js file over 300k lines of code where the following was declared:
var app = {};
Beyond that everything in the app is written as such.
app.somefunction = function(args, callback) {
some code
};
This apparently allowed for the author to handily use Eclipse IDE "outline", which I confess I have started to enjoy having, never previously having been an IDE user I'm becoming a convert to the niceties they provide.
My question is, as I work on a phased refactor of this huge codebase, potentially trying to merge it into some sort of more established framework perhaps using something like require.js, is it OK to split the "app.js" up into smaller files and for the sake of sanity to be able to use the IDE outline declare app to be equal to itself in each one.
app = app;
I've tested this, it works from what I can tell and it allows the IDE to add all the subsequent functions to the outline window while making the project a little more manageable while I learn what it is actually doing. Are there any drawbacks to doing this? I imagine some async loading issues might occur; this could possibly add to client side overhead; or is this perfectly acceptable?
I realize that this is sort of a code philosophy question, but the simple Q&A would be, what effect would app=app; have?
There's no problem doing that.
In fact, this is pretty common code:
var app = app || {};
to initialize a variable only if it doesn't already have a value. In the case where it does already have a value, it will be exactly equivalent to your app = app;
This technique can also be useful for initializing a large object like you have in multiple chunks, allowing you to reorder and omit chunks at will, while being sure that no chunk is going to wipe another's initializations by doing var app = {}

Nodejs app structure

I'm wondering if I'm structuring my nodejs app accordingly to account for best performance. My major concern is in regards to how I'm passing in moving my app reference around modules.
Basically in my app.js file I'm declaring all of my requires, libraries etc:
var app = {
config : require('../../config.json'),
restify : require('restify'),
path : require('path'),
mongo : require('mongodb'),
model : require('./models.js'),
step : require('step'),
q : require('q'),
api : require('./api_util.js'),
underscore : require('underscore')
};
In my exports I'm passing in the entire app object. Now given my knowledge of JavaScript (you can correct me if I'm wrong), this will not create new instances of the object, it will simply pass in the object as a pointer and reference the same object in memory.
Now what I find myself doing aside from that (for ease) is in my restify library (the same can be done with Express), I'm appending the app value to the server request object like so:
app.server.pre(function (request, response, next) {
request.app = app;
return next();
});
Hence on every single request if I need quick access to any of my library declarations, config etc. I can easily access request.app. I don't see this being an issue either, same logic the object acts a pointer back to the same memory space, so I'm not doubling memory usage or anything.
Is there a better/easier way of structuring this?
You are correct about references being passed instead of objects being duplicated. From that point of view, you are not wasting extra space when passing references to your app.
However, I would advise you against doing this: if you pass a reference to app around everywhere, what it tells me is that you don't really know what you will need in this or that module.
You should carefully plan your dependencies and know what each module will need so that you can pass the right dependencies for each module in your app.
Regarding things like underscore or mongodb, you should not be doing what you are doing. You should only pass around modules that need initialization. For things like underscore or mongodb, node.js caches the definition the first time you require() it, so you can really call require at the top of every module that needs it.
This will not incur any performance loss, and it will make it clearer what library each module requires.

Categories