领域驱动设计(Thoughtworks洞见)
上QQ阅读APP看书,第一时间看更新

Repositories的使用

Repositories是一个非常容易被误解的抽象,很多人会直接联想到具体的数据存储。在初期采用DDD建模的时候,我经常刻意回避这个抽象,避免让大家陷入思考紊乱。

这个抽象概念实际可以追溯到Martin Fowler的Object Query模式。另外一个相关概念是DAO(Data Access Object),都是用来简化需要存储的数据和对应的业务对象之间的映射关系。不同的是Repositories针对更加粗颗粒度的抽象,在DDD这个方法里我们可以认为映射对象是我们的聚合。针对每个实体在实现时候也可能创造出对应的DAO(比如采用Hibernate这样的ORM框架),但显然在建模过程中不是我们需要关注的。

那么Repositories的抽象为什么是必要的呢?让我们再回到订单跟踪这个例子,通知订单状态发生变化的服务在发出通知前,需要定位到订单的信息(可能包括订单的相关干系人和子订单的信息)。通知作为一个服务是不应该持有具体订单信息的,这个时候我们就需要通过Repositories的抽象来建立对订单这个聚合的查询,即有一个订单的repo,而具体的查询逻辑应该在这个repo中。

这样的抽象在需要存储和查询值对象的时候也是必要的。假设我们分析订单查询这个领域,在这个领域里订单记录显然已经不允许修改了,自然的抽象方式就是值对象。同时一个查询的服务来持有具体的查询逻辑(比如按时间或用户)是合理的。外部应用直接调取了查询服务(接口)并给出规定的参数,我们就需要一个订单记录的repo来持有跟存储相关的查询逻辑。当然这并不是说有一个查询就一定有一个repo与之对应,如果查询的逻辑非常简单,未尝不可以让服务直接针对数据存储实现。记住我们抽象的目标是让建模更简单,抽象过程中应该保持灵活。