实现领域驱动设计-资源库

资源库

资源库类比熟悉的DAO,简单理解就是一个持久化机制。

通常我们将聚合实例存放在资源库中,之后再通过该资源库来获取相同。如果你修改了某个聚合,那么这种改变将被资源库所持久化。如果你从资源库中移除了某个实例,那么从那以后你将无法重新获取该实例。

从DDD来说,只有聚合才拥有资源库,也就是一般都是说某某聚合的资源库,比如ProductRepository。

资源库有两种实现风格:面向集合的资源库和面向持久化的资源库。主要是接口风格的不同

面向集合资源库

面向集合的资源库,接口跟集合接口设计类似,如提供add,addAll,remove,removeAll,看起来就像在操作集合对象一样

面向集合资源库,需要持久化机制提供特殊支持,比如隐式的跟踪发生在某个持久化对象上的改变,这样才能支持“要修改其中一个对象,我们只需要先从集合中获取到该对象的引用,然后在该对象上执行行为方法即可”,为了实现隐式变化跟踪,有隐式读时复制和隐式写时复制,但都需要大量的内存和一些代理操作,都会有性能上的损耗,所以这是实现的一个考虑因素。

另外参照集合的add方法行为,面向集合资源库add时,只要集合中存在该聚合实例,添加就会失败,不论实例的属性是不是有变化。这也另一方面说明,资源库应该模拟集合的接口和行为,屏蔽持久化机制。

面向持久化资源库

面向持久化的资源库,接口风格和行为上,会照顾持久化机制的实现,比如提供save,saveAll,remove,removeAll,而重要是:对聚合实例的修改,需要显式的调用save方法,完成实例的持久化更新

持久化组件

RDB:mysql,oracle

Nosql:Coherence,MongoDB,GemFire,还有常见的redis

ORM:Hibernate,TopLink,还有常用的mybatis

资源库VS数据访问对象DAO

DAO主要是从数据库表的角度来看待问题,来提供CRUD操作。表模块,表数据网关和活动记录,是DAO相关模式,是数据库表的一层封装,用于事务脚本程序中,而资源库和数据映射器(Data Mapper)则更加倾向于对象,因此通常被用于领域模型中。而资源库的接口设计,也应该是通用语言的表达

管理事务

“对事务的管理绝对不应该放在领域模型和领域层中。通常来说,与领域模型相关的操作都非常细粒度的,以至于无法用于管理事务,另外,领域模型也不应该意识到事务的存在”,通常事务应该放在应用层,然后为每个主要的用例创建一个门面(facade),门面的业务方法都是粗粒度的,然后一个业务方法对应一个事务,比如使用声明式事务:

public class SomeApplicationServiceFacade {

    @Transactional

    public void doSomeUseCaseTask() {

        // 使用领域模型

    }

}

然后问题是:

在应用服务门面的业务方法使用事务,而粗粒度的业务方法,不是容易使用到多个域名模型修改多个聚合吗?违反了一个事务只修改一个聚合的原则啊?

而聚合代表着事务边界,而资源库是给聚合提供存取操作的,那么代表事务边界的注释,不是应该加在资源库接口上吗?

你可能感兴趣的:(实现领域驱动设计-资源库)