解构领域驱动设计(三):领域驱动设计

在上一部分,分层架构的目的是为了将业务规则剥离出来在单独的领域层中进行实现。再回顾一下领域驱动设计的分层中应用层代码的实现。@Overridepublic void pay(int orderId, float amount) { DesignerOrder order = designerOrderRepository.selectByKey(orderId); // 领域对象的加载 if (order == null) { AppException....
摘要由CSDN通过智能技术生成

 

在上一部分,分层架构的目的是为了将业务规则剥离出来在单独的领域层中进行实现。再回顾一下领域驱动设计的分层中应用层代码的实现。

复制代码

@Override
public void pay(int orderId, float amount) {
    DesignerOrder order = designerOrderRepository.selectByKey(orderId);   // 领域对象的加载
    if (order == null) {
        AppException.throwAppException(AppExceptionMessage.DESIGNER_ORDER_NOT_EXIST_CODE, AppExceptionMessage.DESIGNER_ORDER_NOT_EXIST, orderId);
    }
    
    order.pay(amount);    // 领域对象业务规则实现
    designerOrderRepository.update(order);    // 领域对象状态持久化
}

复制代码

 

所有的业务规则都抽象到领域对象,比如“order.pay(amount)”抽象了付款的业务规则。领域对象由状态(对象的字段、属性)和操作(对象的方法)构成,领域对象的操作用于实现业务规则,业务规则执行完成后更改领域对象的状态。领域对象的持久化交给了基础设施层,这里,Repository目的是持久化领域对象状态。

领域驱动设计,即领域模型驱动程序设计,它的核心是保证系统的实现与实际的业务规则一致,完整实现了领域模型。它包含了两个部分:领域模型、领域模型的编程实现。

在软件设计和实现过程中要充分利用领域模型,设计过程中,领域模型作为与业务专家的沟通语言;实现过程中,领域模型作为与开发人员沟通的语言。领域模型在软件生命周期过程作为通用语言。

1 领域模型

领域建模(这里不重点介绍如何建模)方法论产出领域模型。我们可以使用UML建模,使用最简单、最容易理解的名词-形容词-动词法对领域知识进行建模,使用该模型作为与业务、技术团队沟通的通用语言。

在名词-形容词-动词法建模方法中,领域知识中的名词一般对应模型、形容词对应模型属性、动词对应模型方法。模型之间的关系有:组合、聚合、关联、依赖,四者关系由强到弱。

依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义。一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。 

关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法。关联可以是双向的,也可以是单向的。在Java语言中,关联关系一般使用成员变量来实现。 

聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如,汽车类与引擎类、轮胎类,以及其它的零件类之间的关系便整体和个体的关系。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。 

组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。代表整体的对象需要负责保持部分对象和存活,在一些情况下将负责代表部分的对象湮灭掉。代表整体的对象可以将代表部分的对象传递给另一个对象,由后者负责此对象的生命周期。换言之,代表部分的对象在每一个时刻只能与一个对象发生组合关系,由后者排他地负责生命周期。部分和整体的生命周期一样。 

简而言之,组合关系表示部分与整体关系,部分不能单独存在;聚合关系表示稍弱的部分与整体关系,部分可以单独存在;关联关系是一个模型和另一个模型的联接,比如一个订单有一个顾客而一个顾客有多个订单;依赖是最弱的关系,表示一个模型的实现使用到另一个模型的功能。

举个例子,我们与业务专家沟通,梳理了如下业务知识,然后我们使用名词-形容词-动词法来进行建模。

=====================
领域知识:装修设计预约平台
1 客户通过系统预约设计师进行装修设计,客户只能预约一个设计师订单,不能预约多个同时进行设计。
2 预约后,设计师上门进行量房,根据面积进行报价和预估设计时间。设计师订单按照4个节点预估交付时间,在不同节点交付不同成果,这四个节点分别为平面图、效果图、施工
图、交底,四个节点的付款比率分别为10%、40%、40%、10%。
3 客户接受报价方案后,进行付款,设计师开始设计;如果拒绝,则设计师可以进行再次报价和预估设计时间。
4 客户在付款之前,都可以进行终止。
5 客户付款后,正式进入设计阶段。设计师按阶段推进设计并按阶段更新进度。在每一个阶段,设计师完成任务后,客户进行阶段成果确认,客户确定后所有阶段后,订单自动完成。
6 客户可以对完成的订单进行评价。
7 客户对已付款但未完成的订单可以提出退款申请,退款计算方法依据当前设计进度,如果当前进度已经达到设计师请求施工图设计确认进度或超过该进度,则不允许退款。如果允许退款,退款金额最多为(总额 - 已完成的各阶段付款之和),最少为未完成交付节点的待付款总额。
8 申请通过的退款订单不再允许更新进度。
=====================

在这里我们可以梳理出来的名词有:客户、设计师订单、设计师、订单交付进度与交付节点、退款订单。
和设计师订单有关的动词有:量房、报价、接受(拒绝)报价、取消、付款、确认进度、退款、评价等。
设计师订单有关的属性有:订单金额、支付金额、面积、取消原因、评价、状态等。

因此,我们通过使用名词-形容词-动词法构建的模型图如下所示。

这里,模型有:客户Customer,设计师Designer,设计师订单DesignerOrder,退款单RefundOrder,设计进度DesigningProgressReport,设计进度节点DesigningProgressNode。模型中组合关系为:设计进度DesigningProgressReport,设计进度节点DesigningProgressNode;其它模型之间的关系为关联关系。

这个模型就作为软件开发和维护过程的通用语言。接下来,我们将介绍如何来实现领域模型。

2 领域模型实现

在上一节,我们介绍了通过领域建模来构建了领域模型。接下来我们要介绍如何实现模型驱动程序设计,即我们如何通过代码来实现领域模型对应的业务逻辑。领域模型的实现代码在领域层,它完整实现了领域模型的内部结构和模型之间的关系。

领域模型的实现代码由以下几个部分构成:
• 领域模型关系的实现:组合、聚合、关联、依赖。
• 领域模型的实现:实体和值对象。
• 跨领域模型的业务规则的实现:领域服务。

2.1 领域模型关系的实现

聚合、组合、关联关系在实现上的表现基本上是一个类(或者类的标识)作为另一个类的属性;而依赖关系则是一个类作为另一个类在方法的实现上的参数、变量,为另一个类提供功能实现。

下面我们简单看一下如何通过编码来实现类关联关系,比如在模型上客户和设计师订单是关联关系,一个客户可以有多个设计师订单,但是每一个设计师订单只能有一个客户和一个设计师并且最多只有一个退款订单。

(1)聚合、组合、关联
表现在一个类持有另一个类的引用,引用可以是实例的引用或者标识的引用,具体实现为属性。这种关系是双向关系,为了简化编码,可能只需要一方持有另一方的引用即可,这依赖于具体要实现的业务逻辑。如下代码实现了DesignerOrder对设计师、进度报告的关系。

复制代码

public class DesignerOrder implements Entity<DesignerOrder> {
    private int id;
    private int designerId;

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值