Design, Build and Release

Ramblings of IainJMitchell on C#, Javascript and Software Craftsmanship

Archive for the ‘nodejs’ tag

A quick introduction to nodejs

leave a comment

Introduction

nodejs is here, it’s going to save the world, long live Javascript!
Oh really?
As Chuck D says “Don’t believe the Hype”, however I’ve been using nodejs for a year or so and I quite like it.

Server side Javascript?

Well it is the simplest definition, but not 100% accurate. Yes, nodejs code is written in Javascript (the clue is in the js part of the name), but it’s actually defined as Event Driven, Asynchronous IO.

  1. Event Driven – eventing is built into the framework, which allows us to pass messages/commands in a nice OO friendly manor (tell don’t ask)
  2. Asynchronous IO – input and output does not block, which means no need for complex thread management

What do I need?

nodejs runs on Windows and Linux (I’d recommend the latter), it can be downloaded from here or directly from the git repository.

Fisherprice, my first node app

require('http')
	.createServer(function (request, response) { 
		response.writeHead(200, {'Content-Type': 'text/plain'});
		response.end('Hello World');
	})
	.listen(1337);

console.log('Server running');

To execute the code we execute node from the command line, using the file name as an argument, e.g.
node helloWorld.js.

This code creates an app that is hosted at http://localhost:1337, when this address is hit the response will be a HTTP 200 (success) with the text ‘Hello World’. Pretty simple and no need for hosting in a separate web server*.

We can also rewrite this example to work with net.tcp:

require('net')
	.createServer(function (socket) {
		socket.write('helloWorld')
	})
	.listen(1330);

It’s all about the modules

You probably noticed the require keyword in the above examples, which is a request to load up a named module. This is possible because nodejs implements the CommonJS standard of defining and loading modules.

This allows us to define our own modules, like so:

var helloWorlder = function(){
	return 'hello world';
};

exports.helloWorlder = helloWorlder;

The exports object allows us to define the API of our module, in this case this is just a simple ‘hello World’ function. If this is saved in a file named aModule.js, then we can utilise this in another node application like so:

var module = require('./aModule.js');

console.log(module.helloWorlder());

Open source == Communism?

Of course, it would be dull world if we kept our node modules to ourselves. nodejs is all about open source and sharing our code, and this is where Node Package Manager (NPM) comes in.

NPM allows you to consume open source node modules and also submit your own. After installation NPM allows you to install modules at the command line, such as the following example for underscore:
NPM install underscore

After successfully running this command, you can then use underscore in your node app:

_ = require('underscore');
var collection = [1,2];
console.log(_.first(collection));

Good practice -> node modules differ from the large client side libraries (e.g. jQuery, Mootools etc), they tend to be smaller and focussed on one particular task.

Eventing

This often overlooked feature of node is implemented through the EventEmitter class, which allows code to publish messages/commands to other subscribing sections of code. Here is an example of a direct use of the event emitter:

var EventEmitter = require('events').EventEmitter;
var publisher = new EventEmitter();

publisher.on('stuff', function(){
	console.log('stuff event fired');
});

publisher.on('stuff', function(){
	console.log('other stuff event fired');
});

publisher.emit('stuff');

When this code is executed the emit call will output the following to the console:
stuff event fired
other stuff event fired

Classes can also inherit from the EventEmitter, allowing them to have their own dedicated subscribers that they can emit to (see my node shopping cart kata for an event driven node solution).

Lessons Learnt

  • Unit Testing – There is a node port of Jasmine, but I’d recommend Vows, which is an asynchronous unit testing framework designed for use with node
  • Coffeescript – This is a language that compiles down into Javascript, it gives you a more ruby like syntax and much easier construction of classes and inheritance. Although the outputted Javascript is a bit too verbose for client side code, it is great for node. More details here.
  • MVCExpress is a lightweight MVC framework for node (think more Sinatra/Nancy rather than ASP.NET MVC).
  • DevelopmentNodeMon can be used to watch files in a directory and restart your node application if they change.

Other useful links

Github repository containing the examples from this post.
Github repository of the shopping kata in nodejs.
Introduction to nodeJs by the creator Ryan Dahl.
@nodejs
@ryah

* Okay, it probably is a good idea to host behind a web server for web facing services, many leading web servers now have support for nodejs processes.

Written by IainJMitchell

May 18th, 2012 at 12:32 pm

Posted in Uncategorized

Tagged with , , ,

Implementing the Repository pattern with MongoDB and coffeescript/nodejs

one comment

The Repository Pattern is a useful mechanism to abstract the mechanics of the data store away from the business logic. There are various ways of implementing a repository against a relational database, the mechanics could use plain old SQL or something more exotic like nHibernate or Entity Framework.

This post is going to look at constructing a generic repository to use against a mongoDB data store, and because I want to show how ‘hip’ I am, the example will be in coffeescript with nodejs.

Prerequisites

You will need:

  • nodejs & mongoDB installed
  • coffeescript npm package (npm install -g coffee-script)
  • mongojs npm package (npm install -g mongojs)

Implementing Create and Read operations

The first requirement of our repository is that it needs to connect to the mongoDB database, which can be implemented in the classes constructor.

database = "localhost/myDatabase"

class Repository
	constructor: (@objectName) ->
		@db = require("mongojs").connect(database, [@objectName])

Within the constructor, the passed in object name and the database connection string are used to retrieve a connection to the database, that includes the specified objects collection. This connection is stored in the class variable db, so it can be accessed in our repository class operations.
N.B. In the example above the database connection is specified as a variable above the class – it would be much better to read this from a configuration file.

To facilitate the management of domain entities or value objects, repositories need to provide CRUD (Create, Read, Update, Delete) operations on the object. As Javascript is a dynamic language and mongoDB is a document datastore, our code for the write operation will be straightforward:

	add: (value) ->
		@db[@objectName].save(value)

The add method takes in the value to add (the object), it then requests the objects collection from the database connection and saves the object to it. This is the equivalent of calling db.myObject.save({object}) on the mongoDB command line. Alternatively, you could use the .add() method, but unlike the .save() method, this will not save the object if it already exists (by uuid) in the collection.

Implementing the CRUD read operation is also fairly straightforward, certainly much simpler than relational database repositories which require specialised query objects to be passed in and repository strategies to be formulated.

	find: (query, callback) ->
		@db[@objectName].find(query, (err, docs) -> callback(docs))

This .find() method accepts a query object that is passed to the mongojs .find() method, which locates any documents (objects) that match this query. The result is passed back to the caller via the passed in callback function.
N.B. It is also possible to identify and log any errors encountered, using the first (err) argument of the mongojs callback.

The example below demonstrates how the .add() and .find() methods can be used to add objects to the data store, and then search for matching documents.

repository = new Repository("Donkey")

donkey1 = {name: "chris", age: 12}
repository.add(donkey1)

donkey2 = {name: "colin", age: 32}
repository.add(donkey2)

query = {age: 12}
repository.find(query, (donkeys) -> 
	console.log donkey for donkey in donkeys
	#expected console output = {name: "chris", age: 12}
)

Updating and Deleting

Now that we have our objects added to the data store, we also need to be able to make amendments to, and delete them. In order to find the records that we want to change, the .update() method must also accept a query object (see below).

	update: (query, value) ->
		@db[@objectName].update(query, {$set: value}, {multi: true})

In addition, to this it also needs to accept the updated value(s), which are encapsulated in the value argument. Both of these are used in the mongojs .update() call executed from within the repository method. The update values are passed as a $set parameter, that ensures that ONLY the fields specified in the value object are updated – none specified fields are left with the value they held prior to the update. It is also worth mentioning that the third argument to mongojs includes a multi property that is set to true – if this is NOT set then only the first matching object will be updated in the collection.

Deleting is much more straightforward, as all our .remove() method needs is a query that specifies the objects that need removing from the collection. So, this can be quite simply implemented as:

	remove: (query) ->
		@db[@objectName].remove(query)

Putting it all together

Our resulting repository code will resemble:

database = "localhost/myDatabase"

class Repository
	constructor: (@objectName) ->
		@db = require("mongojs").connect(database, [@objectName])
	add: (value) ->
		@db[@objectName].save(value)
	find: (query, callback) ->
		@db[@objectName].find(query, (err, docs) -> callback(docs))
	update: (query, value) ->
		@db[@objectName].update(query, {$set: value}, {multi: true})
	remove: (query) ->
		@db[@objectName].remove(query)
		
exports.Repository = Repository

N.B. The exports is required to make it available in a different file, through the nodejs require command.

Here is an example of all the repository methods being exercised:

repository = new require("./Repository.js").Repository("Donkey")

donkey1 = {name: "chris", age: 12}
repository.add(donkey1)

donkey2 = {name: "colin", age: 32}
repository.add(donkey2)

query = {age: 12}
repository.find(query, (donkeys) -> 
	console.log donkey for donkey in donkeys
	#expected console output = {name: "chris", age: 12}
	query2 = {name: "chris"}	
	repository.update(query2, {age: 100})
	#chris's age set to 100
	repository.remove(query2)
	#chris removed
)

Conclusion

In this post I have demonstrated how a generic repository can easily be implemented in a dynamic language against a mongoDB database. You may very well be asking that if it is so simple then why bother with the repository at all? I would always argue that the abstraction of the data store is crucial to even the simplest of applications, what if the data suddenly needed to be stored in a different data store? By abstracting the data store logic out, we keep our domain code lean and free of vender specific implementation detail.

UPDATE

This repository implementation is now available on through Node Package Manager (NPM).

npm install mongorepository

Written by IainJMitchell

January 2nd, 2012 at 2:24 pm