DDD

零、为什么DDD?

一、DDD与微服务

DDD和微服务有着天生的默契。比如一个微服务应该对应DDD中的一个限界上下文(Bounded Context),限界上下文是软件模块化的一种体现。在微服务设计中应该首先识别出DDD中的聚合根(Aggregate Root)。还有在微服务之间集成时采用DDD中的防腐层(Anti-Corruption Layer, ACL)

1.1 聚合根

聚合根就是软件模型中那些最重要的以名词形式存在的领域对象,比如会员管理系统中,会员(Member)便是一个聚合根;对于报销系统,报销单(Expense)便是一个聚合根;对于保险系统,保单(Policy)便是一个聚合根。聚合根是主要的业务逻辑载体,DDD中所有的战术实现都围绕着聚合根展开,核心的业务逻辑被内聚在行为饱满的领域对象。

1.2 聚合

聚合是对业务规则的封装。以上面那个订单跟踪领域为例,假设我们允许一个订单下存在多个子订单,而每个子订单也是可以独立配送的,这种情况下我们抽象出“子订单”这个实体。显然订单和子订单存在业务逻辑上的一致性,没有订单的时候不应该创建子订单,更新子订单的时候应该同时“通知”所属的订单。这个时候如果采用把订单和子订单聚合起来的封装就很有必要了。显然这样的好处是在订单跟踪这个领域模型里,订单作为一个聚合存在,我们只需要一次性梳理清楚订单和子订单的逻辑关系,就不需要在未来每次引用时都考虑这里面的业务规则了。

1.3 限界上下文

一个限界上下文封装了一个相对独立子领域的领域模型和服务。限界上下文地图描述了各个子领域之间的集成调用关系。这个定义某种意义上和我们的微服务划分不谋而合:以提供业务能力为导向的、自治的、独立部署单元。

二、DDD实战 - 如何写代码

2.1 分层架构

我们的核心实体(Entity)和值对象(Value Object)应该在Domain层,定义的领域服务(Domain Service)在Service Layer,而针对实体和值对象的存储和查询逻辑都应该在Repositories层。值得注意的是,不要把Entity的属性和行为分离到Domain和Service两层中去实现,即所谓的贫血模型。

2.2 业务分包

基于业务分包(package),就是通过软件所实现的业务功能进行模块化划分、而不是从技术的角度划分(比如首先划分出service和infrastruture等包)。通常的做法便是基于聚合根进行顶层包的划分。比如电商项目中,有两个聚合根对象Order和Product,分别创建order包和product包。通过REST API接口返回Product数据时,代码中涉及到了两个对象ProductRepresentationService和ProductSummaryRepresentation,这两个对象是紧密关联的,因此将他们放在representation子包下。可以看到,我们专门创建了一个model包用于放置所有与Order聚合根相关的领域对象;另外,基于同类型相聚原则,创建command包和exception包分别用于放置请求类和异常类。

2.3 application service

DDD专门提供了一个名为应用服务(ApplicationService)的抽象层。ApplicationService采用了门面模式,作为领域模型向外提供业务功能的总出入口,就像酒店的前台处理客户的不同需求一样。ApplicationService的实现遵循一个很简单的原则,即一个业务用例对应ApplicationService上的一个业务方法。

2.4 repository

通俗点讲,资源库(Repository)就是用来持久化聚合根的。从技术上讲,Repository和DAO所扮演的角色相似,不过DAO的设计初衷只是对数据库的一层很薄的封装,而Repository是更偏向于领域模型。另外,在所有的领域对象中,只有聚合根才“配得上”拥有Repository

2.5 实体Entity和值对象value object

这两个抽象方式在定义上的区别是,实体需要给予一个唯一标识,而值对象不需要(可以通过属性集合标识)。当然另外一个经常引用的区别是,实体应该是有一个连续的生命周期的,比如我们在一个订单跟踪领域里抽象订单为一个实体,那么每个订单应该有一个唯一识别号,订单也应该有从下单创建到最后交货完成的生命周期。

值对象的意义在于,当一个对象在我们(抽象)的世界里不能改变的时候,一切都变得简单了,这个对象被创建后只能被引用,当没有引用时我们可以把它交给垃圾回收自动处理。

2.6 领域服务

我经常会用静态方法来帮助技术人员理解服务的抽象(虽然服务并不一定用静态方法来实现)。服务本身就像一个静态方法一样,拥有一定的逻辑但不持有任何的信息,从整个领域来看也不存在不同“版本”的同一个服务。

三、DDD设计实例

你可能感兴趣的:(DDD)