Node.js应用程序中的域驱动设计

Daw*_*iak 33 javascript domain-driven-design node.js

TL; DR; 我正在寻找DDD node.js应用程序的一些例子.


嗨,

我要创建节点应用程序.我想知道我找不到任何在域中分离业务逻辑的应用程序示例.

好的,有一些例子:https: //github.com/adrai/node-cqrs-domain - 但这是整个CQRS与事件采购实现.

我的想法是那样做:

//domain/book.js
function Book(title, author)
{
  this._title = title;
  this._author = author;
}

// domain methods ...

//infrastructure/persistance/repository/book-repository.js
function BookRepository()
{}

BookRepository.prototype.save(book)
{
  var bookModel = mappers.mapToOrm(book);
  return bookModel.save();
}

// [...] get, getAll, getNextId

//infrastructure/persistance/orm/book.js
//using http://bookshelfjs.org/
var Book = bookshelf.Model.extend({
  tableName: 'books'
});

//infrastructure/mappers/book-mapper.js
function mapToOrm(book) {
  //mapping [...]
  return new persistance.Book();
}

function mapToDomain(domain) {
  //mapping [...]
  return new domain.Book();
}
Run Code Online (Sandbox Code Playgroud)

但另一方面,我从未见过任何类似的解决方案(使用域模型,orm模型,存储库和映射器).我是以正确的方式思考的吗?也许没有理由在node.js应用程序中分离域中的业务逻辑.如果是这样,为什么?如果没有,你能给我一个DDD实现的例子或改进我的代码吗?

[2017年1月13日]

我在TypeScript中创建了示例应用程序.目前没有存储库,没有太多服务.欢迎提出问题和拉取请求. https://github.com/dawiddominiak/ddd-typescript-bin-packing-problem-solution

Wah*_*tar 6

我是Node.js世界的新手。

但是我相信,如果您将TypeScript与Node结合使用可以强制使用大多数DDD原理。

在node.js中“同时具有优势”的问题没有像我们在C#或Java这样的OOP语言中所具有的限制那样多。JavaScript的这种自由和“混乱” 使得很难创建健壮的复杂DomainModel和业务逻辑

  • 不用TypeScript就能很好地构建DDD。说一种语言是“凌乱的”,而DDD很难用它来表达,这是由于对该语言缺乏了解。 (2认同)
  • @VedranMaricevic。DDD 更适合 OOP 语言,这个问题最有力的证明就是这个问题。欢呼;) (2认同)

Mis*_*dle 5

我目前正在做同样的事情,而且我来自 Ruby 世界。所以,让我做两件事:

  1. 向您指出我发现的领域驱动设计中最好的 Ruby 实现,Hanami:http ://hanamirb.org/guides/models/overview/ ,您可以将其用作参考。

  2. 讨论我的发现(字面意思是现在,当我输入时)以尝试在 Node.js 中找到类似物。

我找到了这个页面:https : //github.com/sindresorhus/awesome-nodejs

其中列出了大量高质量/高人气的 Node 包。

第一件事是,我们需要一些东西来为我们的领域模型进行验证和模式构建。看看数据验证部分的第一个条目,Joi 似乎是一个不错的选择:

https://github.com/hapijs/joi

对于域对象的持久性,我只是设置了一个存根对象,借用 Hanami 的界面:

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
Run Code Online (Sandbox Code Playgroud)

无论您选择使用BookshelfSequelize还是LoopBack框架,您都可以编写一个适合上述接口的对象,然后完成与这些框架集成的繁琐工作。

如果我要尝试不同的 ORM,我会为上述每个对象创建一个不同的 repo 对象。请注意,正如我所写的,repo 是一个单例,它知道不同的实体以及如何持久化它们。在许多情况下,这无疑会在每个实体的基础上委托给不同的存储库对象。然而,这可能并不总是正确的。一个简单的内存存储库,每个实体可能只有一个对象数组。

剩下的服务/交互器 - 实际工作的函数/类。这些很简单——它们是接受域对象,执行一些业务逻辑,并且在 CRUD 情况下,调用存储库的那些。一个可能语法错误的例子:

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
Run Code Online (Sandbox Code Playgroud)

对于服务功能,我今天刚刚了解了节点机器,它们似乎是一个非常聪明的想法:http : //node-machine.org

它们似乎是对 monads + 文档的 JS 尝试。所以我正在考虑这样写。

无论如何,鉴于您的帖子已经一年了,您可能已经继续前进了。希望这对您/社区有所帮助!