Very-Loose Coupling and Dependency Injection for Database Management

Architecturedependency-injectiondesign-patternsmongodb

I'm currently setting up a MongoDB database for a web-app. I'm running node.js and using Mongoose to help manage mapping, validation ect.

I'm wondering if it's a good idea to really decouple MongoDB from my code, just on the off-chance we want to switch to something like CouchDB a little later. Specifically, I'd make a databaseManger module that is responsible for setting up Mongoose/Mongo, defining the mongoose models, managing replica sets, and doing some extra validation. This manager would export a generic API, and handle the details of the queries internally. The manager would then be passed around via dependency injection.

Does this make sense? Or am I kind-of redoing some of the mongoose functionality?

Any advice is appreciated.

Best Answer

I always try and abstract out data access out of my application code. In node.js, I create repositories for managing data access to any top-level item (aggregate-root, in DDD terms).

Those repositories expose a very clean domain-friendly API to the application, which hides any implementation detail - such as whether it uses MySQL or MongoDB as a back-end. It also converts the raw database-returned data, into a proper domain object.

In a more traditional language, some of those methods would look like this (let's use an ad repository as an example):

Ad #find(id)
Ad[] #findAll()
Ad[] #findByVendor(vendor)

Or, more asynchronously:

#find(id, cb)
#findAll(cb)

Those callbacks should accept err, and then the constructed domain object(s) as the second data parameter.

Also, try and avoid just having basic CRUD interactions, instead try to expose things that actually have meaning in your application.

The other added benefit is that your application code is all much easier to test in isolation, because it's not talking to MongoDB or Mongoose directly.