Code Review: Finance
Code Review is a new series on DailyJS where I take a look at an open source project to see how it’s built. Along the way we’ll learn patterns and techniques by JavaScript masters. If you’re looking for tips to write better apps, or just want to see how they’re structured in established projects, then this is the tutorial series for you.
The purpose of these code reviews is not to nitpick; it is simply to learn and hopefully educate. I intend to cover all aspects of JavaScript — the various server-side interpreters, browser-based code, jQuery plugins — anything I find with something to teach us.
This week’s code review is on Finance by TJ Holowaychuk.
Finance
Finance is a little accounting web app. It seems like something useful for logging things like business expenses (I always forget to do that!), but it could be used for any kind of payment.
Installation
You’ll need Node and npm to use Finance.
Check the code out with Git, then set up the packages with npm:
git clone https://github.com/visionmedia/finance.git
cd finance
npm install
Usage

Running node app.js should bring up an instance of Finance. No database setup or authentication is necessary. Try filling in a few payments to get a feel for the app.
App Structure
I was looking for a database library, but I found something interesting! TJ has opted to use a built-in database library, db.js, which writes JSON to a file. The default data is saved to /tmp/finance.db which is worth changing if you actually want to use the app.
Saving data just writes out JSON.stringify(this), and loading it involves reading the file and iterating over each value:
/**
* Load data.
*
* @param {Function} fn
* @api public
*/
Database.prototype.load = function(fn){
var self = this
, fn = fn || noop;
fs.readFile(this.path, 'utf8', function(err, json){
if (err) return fn(err);
var data = JSON.parse(json)
, keys = Object.keys(data)
, len = keys.length;
for (var i = 0; i < len; ++i) {
self[keys[i]] = data[keys[i]];
}
fn();
});
return this;
};
I like how he writes to this rather than an object inside Database.
Of course, this app is built with Express. TJ has structured his main app.js file in an interesting way — it loads the libraries, does the configuration, then loads controllers from separate files:
var month = app.resource('month', require('./controllers/month'));
var items = app.resource('items', require('./controllers/item'));
month.add(items);
This works by using the express-resource module. This patches Express, which is why the var Resource = require('express-resource') line looks slightly suspicious given that Resource doesn’t appear anywhere else.
I have a feeling we might see this practise become popular in Express app development. Even though it’s tempting to keep adding routes to app.js, keeping a slim main file makes managing code easier as a project grows over time (as I found with Nodepad).
Controller Methods
TJ uses res.end() in methods that don’t need to return anything:
exports.update = function(req, res, next){
var month = req.params.month
, id = req.params.item
, data = req.body.item[id]
, item = db.months[month].items[id];
try {
validate(data, 'entity');
validate(data, 'date', 'date');
validate(data, 'category');
validate(data, 'amount', 'number');
for (var key in data) item[key] = data[key];
item.tags = parseTags(item.tags);
db.save();
res.end();
} catch (err) {
res.send({ error: err.message });
}
};
I know that res.send() sends a HTTP 204 No Content response in Express, so presumably this ends the HTTP connection without returning any headers.
The controllers are written using RESTful methods: index, create, update, destroy. There’s also a validation method which throws exceptions when a validation fails. The controller method catches this and sends an error back using JSON: res.send({ error: err.message }).
Views
The views are written with Jade, naturally, and they’re very straightforward. Most of the interface is generated by client-side JavaScript, so the views are mostly placeholders. The items for the index action are rendered by the server rather than putting everything in the client. TJ uses the collection option for partial to do this:
!= partial('item', { collection: items })
!= partial('item', { object: {}})
Client-Side JavaScript
The client-side code is a fairly typical jQuery brain dump. I noticed that TJ aliased jQuery’s function with var j = $; because he hates typing $ (I think he bemoaned this on Twitter).
Conclusions
This is a small project that showcases some of TJ’s new Express modules, and isn’t intended to be used as a multi-user web app. The cunning use of JSON as the database is notable, purely because it makes installation and backup a breeze. Rather than forcing users to install modules for a database (and perhaps even the database itself), they can stick Finance on their laptops and potentially even leave the JSON file in something like Dropbox.
In fact, the entire project has a strangely self-contained yet efficient feel about it, which appeals to me as a way to build nifty little open source web apps.
