DDD理论学习系列——案例及目录


1. 引言

单从字面理解,不管是领域服务还是应用服务,都是服务。而什么是服务?从SOA到微服务,它们所描述的服务都是一个宽泛的概念,我们可以理解为服务是行为的抽象。从前缀来看,根据DDD的经典分层架构,它们又隶属于不同的层,应用服务属于应用层,领域服务属于领域层。

  • 应用层(Application):负责展现层与领域层之间的协调,协调业务对象来执行特定的应用程序任务。它不包含业务逻辑。
  • 领域层(Domain):负责表达业务概念,业务状态信息以及业务规则,是业务软件的核心。

所以综合来看应用服务是用来表述应用行为,而领域服务用来表述领域行为。
那怎么理解应用行为和领域行为呢,应用行为描述了一个具体操作从开始到结束的每一个环节,而领域行为是对应用行为的细化,用来处理具体的某一个环节。比如,我们手机购物,从购物车结算这一场景来举例,这就是一个应用行为。而这个应用行为又主要包括金额计算、支付、生成订单,这些子环节就可以理解为一个领域行为。

我们就不咬文嚼字了,下面我们就一一展开。

2. 应用服务

应用服务是用来表达用例和用户故事(User Story)的主要手段。

应用层通过应用服务接口来暴露系统的全部功能。在应用服务的实现中,它负责编排和转发,它将要实现的功能委托给一个或多个领域对象来实现,它本身只负责处理业务用例的执行顺序以及结果的拼装。通过这样一种方式,它隐藏了领域层的复杂性及其内部实现机制。

应用层相对来说是较“薄”的一层,除了定义应用服务之外,在该层我们可以进行安全认证,权限校验,持久化事务控制,或者向其他系统发生基于事件的消息通知,另外还可以用于创建邮件以发送给客户等。

应用层作为展现层与领域层的桥梁。展现层使用VO(视图模型)进行界面展示,与应用层通过DTO(数据传输对象)进行数据交互,从而达到展现层与DO(领域对象)解耦的目的。

3.领域服务

领域层就是较“胖”的一层,因为它实现了全部业务逻辑并且通过各种校验手段保证业务正确性。而什么是业务逻辑呢?业务流程、业务策略、业务规则、完整性约束等。

当领域中的某个操作过程或转换过程不是实体或值对象的职责时,我们便应该将该操作放在一个单独的接口中,即领域服务。请确保该服务和通用语言时一致的;并且保证它是无状态的。

根据这句话我们有几个问题需要理清:

  1. 什么时候使用领域服务?
  2. 领域服务无状态怎么理解?

领域服务是用来协调领域对象完成某个操作,用来处理业务逻辑的,它本身是一个行为,所以是无状态的。状态由领域对象(具有状态和行为)保存。

上面也说了,领域对象是具有状态和行为的。那就是说我们也可以在实体或值对象来处理业务逻辑。那我们该如何取舍呢?
一般来说,在下面的几种情况下,我们可以使用领域服务:

  • 执行一个显著的业务操作过程
  • 对领域对象进行转换
  • 以多个领域对象为输入,返回一个值对象。

4. 案例分析

我们拿经典的转账问题来分析一下:
而针对转账这一操作,它的业务用例应该是这样的:

  1. 检查账号余额是否足够
  2. 检查目标账户账号是否合法
  3. 转账
  4. 短信通知转账双方

其中1,2步是转账的合法性校验属于转账业务的一部分,所以,1,2,3均应该放到领域层通过领域服务来实现。短信通知,它并不是是转账的核心业务,因为这根据具体情况而定,比如只有客户订阅了账号变动通知我才发短信。所以将第4步归类到应用服务中去实现,就确保了领域服务的纯粹性。

而至于持久化的问题,我们可以这样想,领域逻辑应该只关心业务逻辑,才能保证领域逻辑的可重用性。将持久化放到应用层,我们就会有更多的选择性。

5.总结

当应用服务中的逻辑趋于复杂时,我们就要小心领域逻辑泄露到应用服务中去。而在使用领域服务时,我们又要避免过度使用,因为会导致贫血领域模型。毕竟有些单一的操作更适合放到领域对象(实体和值对象)中去。

所以总结以下:

  1. 服务是行为的抽象。
  2. 应用服务通过委托领域对象和领域服务来表达用例和用户故事。
  3. 领域对象(实体和值对象)负责单一操作。
  4. 领域服务用于协调多个领域对象共同完成某个业务操作。
  5. 应用服务不处理业务逻辑,领域服务处理业务逻辑。

参考资料
DDD与分层架构--秋水逍遥

DDD理论学习系列(8)-- 应用服务&领域服务的更多相关文章

  1. DDD理论学习系列(9)-- 领域事件

    DDD理论学习系列--案例及目录 1. 引言 A domain event is a full-fledged part of the domain model, a representation o ...

  2. DDD理论学习系列(2)-- 领域

    DDD理论学习系列目录 1. 引言 领域一词,主要有以下两个意思: 一国主权所达之地. 学术思想或社会活动的范围. 不管是指国家的主权范围也好还是学术活动范围,都是在讲一个范围,一个界限. 比如我们常 ...

  3. DDD理论学习系列(10)-- 聚合

    DDD理论学习系列--案例及目录 1.引言 聚合,最初是UML类图中的概念,表示一种强的关联关系,是一种整体与部分的关系,且部分能够离开整体而独立存在,如车和轮胎. 在DDD中,聚合也可以用来表示整体 ...

  4. DDD理论学习系列(11)-- 工厂

    DDD理论学习系列--案例及目录 1.引言 在针对大型的复杂领域进行建模时,聚合.实体和值对象之间的依赖关系可能会变得十分复杂.在某个对象中为了确保其依赖对象的有效实例被创建,需要深入了解对象实例化逻 ...

  5. DDD理论学习系列——案例及目录

    目录 DDD理论学习系列(1)-- 通用语言 DDD理论学习系列(2)-- 领域 DDD理论学习系列(3)-- 限界上下文 DDD理论学习系列(4)-- 领域模型 DDD理论学习系列(5)-- 统一建 ...

  6. 应用服务&领域服务

    应用服务&领域服务 DDD理论学习系列——案例及目录 1. 引言 单从字面理解,不管是领域服务还是应用服务,都是服务.而什么是服务?从SOA到微服务,它们所描述的服务都是一个宽泛的概念,我们可 ...

  7. DDD理论学习系列(6)-- 实体

    DDD理论学习系列--案例及目录 1.引言 实体对应的英语单词为Entity.提到实体,你可能立马就想到了代码中定义的实体类.在使用一些ORM框架时,比如Entity Framework,实体作为直接 ...

  8. DDD理论学习系列(12)-- 仓储

    DDD理论学习系列--案例及目录 1. 引言 DDD中Repository这个单词,主要有两种翻译:资源库和仓储,本文取仓储之译. 说到仓储,我们肯定就想到了仓库,仓库一般用来存放货物,而仓库一般由仓 ...

  9. DDD理论学习系列(13)-- 模块

    DDD理论学习系列--案例及目录 1. 引言 Module,即模块,是指提供特定功能的相对独立的单元.提到模块,你肯定就会想到模块化设计思想,也就是功能的分解和组合.对于简单问题,可以直接构建单一模块 ...

随机推荐

  1. 转:Redis配置文件详解

    配置与特性详解 1. 在redis中,合法的"尺寸单位",无大小写区分. # 1k => bytes # 1kb => bytes # 1m => bytes # ...

  2. VR全景智慧城市——“海市蜃楼”般的逛街体验

    <史记·天官书>:"海旁蜃气像楼台:广野气成宫阙然." 海市蜃楼,简称蜃景,是一种因为光的折射和全反射而形成的自然现象,是地球上物体反射的光经大气折射而形成的虚像. 2 ...

  3. 密码学之DES/AES算法

    本文示例代码详见:https://github.com/52fhy/crypt-demo DES DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算 ...

  4. Android studio 断点技巧

    写代码不可避免有Bug,通常情况下除了日志最直接的调试手段就是debug:那么你的调试技术停留在哪一阶段呢?仅仅是下个断点单步执行吗?或者你知道 Evaluate Expression , 知道条件断 ...

  5. JDK的并发容器

          除了提供诸如同步控制,线程池等基本工具外,为了提高开发人员的效率,JDK已经为我们准备了一大批好用的并发容器,这些容器都是线程安全的,可以大大减少开发工作量.你可以在里面找到链表.Hash ...

  6. 华为路由器AR1220F-S的端口映射NAT配置(拨号光纤上网)

    telnet 登录 或者ssh登录路由器 //进入系统试图界面 sys-view //第一步. 添加acl规则, 允许内网本身访问对外的公网ip. 否则,只能外部人员访问你的公网ip [Huawei] ...

  7. webpack的多文件打包问题

    1.第三方库如vue,vue-router可以利用webpack中的entry指定vendor:['vue','vue-router']来打包在一个文件中 2.将这些文件单独提取出来,在页面中使用&l ...

  8. c++ 自动应用类型转换

    c++中,在赋值时如果类型不匹配,就会应用到:类型转换.类型转换又分为隐式转换(implicit conversion) 和 显式强制类型转换(emplcit conversion).在这我围绕着类的 ...

  9. malloc与new相关

    前言: 通常我们使用数组的时候:必须提前用一个常量来指定数组的长度,同时它的内存空间在编译的时候就已经被分配了.但是有时候数组的长度只有在运行的时候才能知道.因此,一种简单的解决方案就是提前申请一块较 ...

  10. ACL配置

    标准acl 1-99:抓源地址 扩展acl 100-199:抓源地址,目标地址,具体数据包(如:icmp,tcp,udp,ospf,ip等) 实验内容 1:ACL实现禁止192.168.1.0网段所有 ...