DDD 仓储

了解仓储

Repository 是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。

用于协调领域和数据映射层,两个关键字领域和数据映射层,这里面的领域是指领域模型(实体和值对象),这是桥的一头,另一头就是数据映射层,也就是我们常说的 ORM 工具

仓储是永久保存领域对象的仓库;在DDD中引入这个概念,是为了隔离业务领域和不同的数据库。
一个对象可以保存到关系数据库,也可以保存到NoSql中;具体的保存形式与数据结构的变化不会对领域对象的实现产生影响。

在DDD中,仓储模式替代了DAO
仓储与DAO的主要区别:

  • 仓储主要是为了保证聚合根对象的加载和保存,同时兼顾一些实体的直接访问;
  • DAO没有这些约束;没有数据所有权概念,没有聚合概念;是数据持久化的接口;

实现仓储

仓储的实现方式

实现仓储可以从两个方式进行:面向集合与面向持久化
面向集合的设计,此时领域当仓储是无限大一个集合,所以仓储只具有集合的概念接口:

  • Add
  • Remove
  • Get

面向持久化的设计,则是将仓储更像是DAO,作为领域对象的持久化过程,此时接口:

  • Save
  • Delete
  • Commit

同一个聚合实例不允许多次添加到仓储中

这个一点,是由于聚合的唯一性,以及仓储的集合特性所共同决定的(在一个集合中不能存在两个相等的对象)。
在仓储的集合设计中,一个对象在更新后,不需要重新执行Add操作,而是在更新时直接作用到这个对象上。
因为仓储中Get出来的对象是对象的引用。

仓储实现方法返回类型建议为void

func Add(TAggregateRoot aggregateRoot) {}

那么如何判断该聚合实例成功添加到了仓储中呢?我们可以自定义一个异常信息,抛出这个异常。

最好不要使用addAll() 和removeAll()方法

建议使用循环调用 Add和Remove方法

聚合中删除聚合实例的含义

在领域驱动设计中,不存在对象删除的说法,正确的表达是,将聚合实例标记为失活的(disable),不可用的(unuseable);也就是所最好不要再仓储中出现delete;至于数据库具体持久化中是否进行delete,就不在仓储的设计中了。

仓储在软件分层中的位置

仓储接口的定义放在了与聚合相同的包中,而仓储的实现类放在基础设施层中(目前我们的方法)。

仓储调用在分层架构中的位置

目前的想法是仓储应该放在领域服务中,在应用服务中只应该看到和传递数据。

参考文献

  1. Repository 仓储,你的归宿究竟在哪


blog comments powered by Disqus
—  原创作品许可 — 署名-非商业性使用-禁止演绎 3.0 未本地化版本 — CC BY-NC-ND 3.0   —