syntaxhighlighter

Sunday, August 26, 2012

DAO - express-examples/sqlite

According to Wikipedia, a DAO "is an object that provides an abstract interface to some type of database or persistence mechanism, providing some specific operations without exposing details of the database. It provides a mapping from application calls to the persistence layer".

This concept just introduces more abstraction and decoupling into your code. In my experience it results fundamental for maintaining painless an app.

Following, an implementation example of this pattern (lib/dao/user.js):

var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('./db/db.sqlite');

this.newInstance = function() {
  return new impl();
};

function impl() {
  // ...

  this.getUsers = function(callback) {
    db.all("SELECT rowid AS id, name FROM user", function(err, rows) {
      if (err) {
        console.log(err);
        rows = null;
      }

      callback(rows);
    });
  };

  // ...
};

As you can see in the code above, we have a class with several methods (specially getUsers). If you want to query the database, you just have to call the necessary method. The rule is simple, group database operations in related classes (e.g. user) and never put a query outside that scope.

Another important thing is: DAO's shouldn't do anything else than database operations, no validation, no business logic! Validations (extra app forms) and "Business Logic" should be put in other classes... You can call them: logics, services, or whatever you want, but separated. Here is an example of a service class (lib/service/user.js):

var userDao = require('../dao/user');

this.newInstance = function() {
  return new impl();
};

function impl() {
  // ...

  this.getUsers = function(callback) {
    userDao.newInstance().getUsers(callback);
  };

  // ...
}

In this example, the service method getUsers doesn't include any business logic, but maybe this can change in the future and for that reason is better to keep it separated.

And finally, you can call the services from a controller or service facade (REST, SOAP, ...) like (lib/rest/user.js and lib/rest/common.js):

var userService = require('../service/user');

this.getUsers = function(req, res) {
  common.call(
    res, 
    null, // No params
    function(params) { return true },
    userService.newInstance().getUsers
  );
};

No comments:

Post a Comment