第23章 命令:用于处理业务用例的应用程序服务模式
探讨引用程序逻辑和领域逻辑之间的区别
为了最大化领域模型的明确性,就迫切需要现实环境领域概念和纯技术问题之间的清晰分离。这一分离是由应用程序服务承担的重要作用之一,它属于应用程序服务层。
从逻辑上讲,应用程序服务位于领域之上,并且依赖于领域。
应用程序服务的一个关键职责是与领域进行协调以便执行完整的业务用例。
作为这一职责的一部分,应用程序必须转换输入和输出以保护领域结构。
- 区分应用程序逻辑和领域逻辑
应用程序逻辑两个通用职责。首先,他们负责基础架构问题:管理事务,发送电子邮件以及类似的技术任务。此外,应用程序必须协调领域以便执行完整的业务用例。
-
- 应用程序逻辑
- 基础架构问题
要调用领域模型的功能,需要执行若干基础架构任务。
1 | 应用程序级别的验证 | 应用程序级别的验证的示例,包括检查正确数据类型,正确格式以及正确长度等。 比如检查电子邮件格式和长度等,他们不是业务规则,也不属于领域范畴。 |
2 | 事务 | |
| 错误处理和错误转换 | 应用程序服务的任务需要处理这些领域抛出的错误情况,并为外部各方将其转换为合适的表述,这样一来外部各方就不会被耦合到领域的错误的结构中,其次也是保证领域知识不泄露。 |
| 日志,指标和监控 | 响应时间,错误和其他类型的诊断信息允许你在查看应用程序执行情况并且在早期阶段发现潜在问题。领域处理这些略显繁琐,作为替代,应用程序承担着职责。 |
| 认证和授权 | 在具体进入到领域逻辑前,进行认证和授权的检查。 |
| 通信 | 有界上下文之间的通信是应用程序服务的职责。 通信的方法有很多,例如RPC过程调用,REST等。 应用程序还需要处理外部事件,处理和发布内部时间以及生成一个Atom源。 |
|
|
|
b. 协调完整的业务用例
应用程序的第二个职责,该职责是会带来价值的:协调领域模型以便完成完整业务用例。
c. 应用程序服务和框架集成
在应用程序服务中,大量的模板冗余代码想办法抽离切面处理。
比如使用Filters,它的行为是管道,使用操作过滤器,实现注入处理验证,开放和关闭事务,日志,以及其他基础框架问题的过滤器。
-
- 来自应用程序服务角度的领域逻辑
对于DDD实践者,区分逻辑是属于应用程序或者领域逻辑是很难的。
决定一系列交互是否属于领域的一种方法是提出
“这种情况总是会出现吗?”,“这些步骤无法分开吗?
如果答案是肯定的,那么可以归属于领域逻辑范畴中。
- 应用程序服务模式
使用命令处理程序,避免将一大堆的应用service放在一个地方。
-
- 命令处理模式
像上面这样创建一个命令和处理程序知识在应用程序中哦为每个用例创建单独接口的基本情况,其目的在于分离职责和提高表述性。
-
- 发布/订阅
用于松散耦合的一种模式是发布/订阅,由此应用程序服务可以订阅领域中的事件。
-
- 请求/回复模式
在选择具有较高复杂性取舍的模式之前,考虑请求/回复模式的简单性总是值得的。
一个常见的约定是,request作文此类的输入模型的前缀,response作为输出。
让响应包含用例的状态,发生失败或者被拒绝后,响应有一个合适的状态码来表示。
-
- async/await
如果需要构建异步,非阻塞式的应用程序,那么需要考虑async和await模式。
使用Task<Customer>可以使用更具线程效率和扩展性的非阻塞式数据库调用。
使用async和await时的优缺点,他们更具资源效率,但是他们会干扰你的代码的信息。
- 测试应用程序服务
可以通过在应用程序服务级别进行测试来覆盖功能或特征的大型垂直切片。
这些类型的测试可以划分为各种分组:包括性能测试,验收测试,集成测试和功能性测试。
-
- 使用领域专业术语
测试会是一个通过UL编写领域概念从而表述领域概念的绝佳机会。
可以使用行为驱动测试(Behavior Driven Development,BDD)与领域专家一起根据其验收标准来创建测试。
-
- 测试尽可能多的功能
- 要点汇总
在于领域通信时,应用程序应该调用领域对象上具有高水平表述性的API。