Domain Driven Design in Node.js Application

I'm very new to Node.js world.

But I believe if you do your work using TypeScript with Node you can force most of DDD principles to be used.

The problem "and advantage in the same time" in node.js that there aren't so restrictions like we have in OOP languages like C# or Java. and this freedom "and messy" of JavaScript making create robust complex DomainModel and Business logic very hard


I'm looking to do the same thing at the moment, and I'm coming from the Ruby world. So, let me do 2 things:

  1. Point you to the best Ruby implementation I've seen of Domain-Driven Design I have found, Hanami: http://hanamirb.org/guides/models/overview/ which you could use as a reference.

  2. Discuss what I'm finding (literally right now, as I type) to attempt to find the analogs in Node.

I've found this page: https://github.com/sindresorhus/awesome-nodejs

which catalogs a ton of high-quality / high-popularity Node packages.

The first thing is, we need something that is going to do validation and schema construction for our Domain Models. Just looking at the first entry in the data validation section, Joi seems to be a decent choice for that:

https://github.com/hapijs/joi

For Persistence of the domain objects, I'm just setting up a stub object, borrowing from Hanami's interface:

var repo = {
  find: function(entity_name, id) {
    //  - Fetch an entity from the collection by its ID
  },
  create: function(entity_name, data) {
    //  – Create a record for the given data and return an entity
  },
  update: function(entity_name, id, data) {
    //  – Update the record corresponding to the id and return the updated entity
  },
  delete: function(entity_name, id) {
    //  – Delete the record corresponding to the given entity
  },
  all: function(entity_name) {
    //  - Fetch all the entities from the collection
  },
  query: function(entity_name, query_object) {

  },
  first: function(entity_name) {
    //  - Fetch the first entity from the collection
  },
  last: function(entity_name) {
    //  - Fetch the last entity from the collection
  },
  clear: function(entity_name) {
    //  - Delete all the records from the collection
  }
}

module.exports = repo

whether you choose to use Bookshelf, Sequelize, or even the LoopBack framework, you can code an object that is going to fit the above interface that then does the dirty work of integrating with those frameworks.

If I were to try different ORM's, I would create a different repo object for each of the above. Notice that as I've written it, the repo is a singleton that is aware of different entities and how to persist them. In many cases, this will no doubt delegate to different repository objects on a per-entity basis. However, that might not always be true. a simple in-memory repo, could just have an array of objects for each entity.

That leaves Services/Interactors - The functions/classes that actually do work. These are easy - they are the ones that take a domain object, perform some business logic, and in the CRUD cases, make a call out to the Repository. A probably-syntactically-wrong example:

const repository = require('./myFileRepository')

function createBook(bookEntity) { 

  if(bookEntity.valid?) { 
    repository.create('book', bookEntity)
    return true
  }
  else {
    return { error: 'book not valid' }
  }
}

module.exports = createBook

for the Service functions, I just today learned about Node Machines, and they seem like a really smart idea: http://node-machine.org

they seem to be a JS-attempt at monads + documentation. so I'm considering writing them up like that.

anyway, given it's been a year since your post, you've probably moved on. hope this helps you / the community!