写点什么

如何使用 DDD 方法验证业务规则

  • 2020-08-17
  • 本文字数:3236 字

    阅读完需:约 11 分钟

如何使用DDD方法验证业务规则

本文要点


  • 业务规则是系统拥有的特定领域知识的一个部分。

  • 合理构建的业务规则可以减少出错概率,并降低维护难度。

  • 不同业务规则的职责不同,例如提供验证或生成输出等。

  • 事件的处理方式决策会影响总体设计,并且在做出任何决策之前都需要了解其后果。

  • 应该围绕用户执行的任务来构造命令方法,并提供清晰的输出。


谈到业务规则,如果你是一名技术人员,可能首先想到的是代码行或业务规则引擎(如果你正在用的话)。但与编码相比,规则更接近知识管理的范畴。例如,建筑部门的员工了解许多关于卧室最小尺寸的规则,或者一片空间定义为卧室或书房的所需特征。如果一个人了解一个领域的规则,知道如何应用它们,就会成为这个领域的专家。我们的目标是创建模拟领域专家行为的软件应用程序。


在本文中,我将使用一个系统来管理公司的共享资源。这套系统的目标是帮助员工预订笔记本、投影仪、乒乓球桌等物品。


光是看上面一句话,你就可以立刻想出一串问题,比如:资源是什么?预订资源意味着什么?系统是否允许多次预订资源?诸如此类的问题应由领域专家回答,并将成为控制系统行为的业务规则。


这也将指导实体、值对象、命令和系统其他元素的定义。如何定义各个元素是更大的主题,超出了本文的范围。


也有专门针对这类主题的书籍,例如 Eric Evans 的《 领域驱动设计》;如果你在实现.NET,我建议你阅读《 使用.NET Core上手领域驱动设计》。


本文只会介绍如何构建业务规则这一部分,这些规则符合以下特征:


  1. 是一致的 。以任何开发人员都可以理解的方式组织规则对未来的更改是非常重要的。如果你认为系统总是在变化,而应用程序应该为这种变化做好准备,那么保持一致就是最佳选择。

  2. 很容易测试 。制定可测试的规则是确保更改不会破坏现有功能的唯一方法。

  3. 保持数据一致性 。保持数据一致是业务规则的主要职责之一。以我的个人经验来说,许多数据质量问题与系统规则处理不当有关。

  4. 很容易诊断 。我们应该努力避免任何意外的错误;但异常总是会发生的。如果你仅有的诊断信息说的是 对象引用为 null ,那么错误就非常严重了。


本文使用"输入-过程-输出"模型来表达系统规则。在这个模型中,一个输入被提供给系统;内部处理器接收输入并执行操作,从而创建输出。但是,在处理器开始执行任何操作之前,它必须验证所提供的信息是否有效。下一节将介绍如何处理这些验证。

模型细节


将命令发送到系统


使用基于域的方法处理验证的基本模型——这里显示了发送到系统的一条命令。


这个模型提供了在系统中处理业务规则的一个实现示例。这种方法基于领域驱动设计( DDD),但不用它而直接应用方法也是可以的。执行顺序如下:

1. 客户端发送一条命令

对于可以由客户端执行的建模命令,我们需要为其分配名称,从而识别它们。例如,它可以是 MakeReservation 之类的名字。注意,我们正在将这些设计定义移至软件设计和业务设计之间的一个中间点上。这听起来没什么特别的,但指定了名称之后,它可以帮助我们更有效地理解系统设计。这个想法是围绕任务而生的,与系统设计的 HCI(人机交互)概念有关。命令可帮助设计人员考虑系统需要支持的特定任务。


命令可能具有其他参数,例如日期、资源名称和用法说明。命令和查询责任隔离( CQRS)是一种使用命令对系统交互进行建模的模式。尽管在模型图解中客户端是一个用户,但它也可能是另一个系统。它还允许那些更改系统状态和仅返回数据的操作在系统的设计中具有不同的行为。



命令的语法验证

2. 语法规则验证

下一步是语法验证。根据 Merriam-Webster 所说,语法是将语言元素(例如单词)组合在一起以构成组分(例如短语或子句)的方式。在我们的上下文中,这意味着命令在领域的上下文中有意义。


这种验证可确保提供的数据对于系统而言是一致的。验证的一个示例是预订的开始日期——其值不应为过去的值,并且不能为 null。在验证阶段有多种返回错误的方法。Vladimir Khorikov 提供了一些有关 如何执行这些验证的示例。验证也可以在系统的不同层中进行。例如,最好在用户界面中通过验证确保提供的日期不是过去的,而不是在后端服务中发送这些值来做验证。这并不是说它也不能用在领域中;它可以防止其他客户端的滥用。



使用系统状态验证语义规则

3. 语义规则验证

语义验证取决于系统状态。此类规则旨在检查给定的命令在给定系统当前状态的情况下是否有意义,当前状态通常是通过系统实体存储和接收的。在 MakeReservation 命令之后,一种验证是检查是否有另一个客户保留了所请求的资源。这种验证也可以在客户端应用程序中进行;尽管如此,领域仍然有很多原因可以收到处理相同资源的预订请求。系统的责任是确保数据一致性。



处理更改系统状态的生产规则

4. 生产规则

生产规则是系统的核心。到目前为止,命令已经历了许多阶段,这些阶段可以确保系统能处理所提供的请求。生产规则指定了系统为达到所需状态而要执行的操作。它们处理的是客户试图完成的任务。它们使用 MakeReservation 命令作为参考,进行必要的更改以将请求的资源注册为保留资源。这些修改的结果是,实体和领域服务可以生成使客户端和其他系统知道更改已发生的事件。在我们一直使用的示例中,它将是 ResourceReserved。



事件的生成与处理

5. 事件

事件是一种与其他系统或子系统交互的通信机制。但是,在你的领域中实现它们之前,有必要确定系统对这些信号的反应方式。事件的处理有两种选项,各有其优缺点。


第一种是使用事务一致性。在这种模式中,系统使用同一事务来保持修改后的实体一致性。即使涉及多个汇总,事务也会跟踪更改并在流程结束时将其保存下来。这种模式称为工作单元。就代码生成而言,它提供了某些优势,例如简单性和效率。但有时它也是不切实际的。原因之一是它将修改后的实体保留在内存中,如果负载太大就会使用过多的内存和处理资源。另外,如果你在领域外通信,则将需要使用分布式事务,结果让应用程序更加复杂。


第二种选项是使用最终一致性。这将增强系统能力,因为你在执行命令时不会在内存中处理一个巨大的实体图。但这种选项会有其他后果。它意味着预订系统已完成其更改,并且如果其他子系统报告了故障,则预订系统必须运行一个补偿事务,还原先前的操作。这种方法还需要告知用户潜在的错误。选择某个选项时应权衡它们各自的优缺点、开发成本和所需的基础架构。例如,系统可能需要消息代理以同其他领域收发消息。



向客户端发送通知

6. 通知

命令完成后,系统必须将执行结果通知客户端。如果客户端是另一个系统,则可以省略此部分。但如果它是一个应用程序,我们可能需要通知用户命令的执行结果是成功还是失败,特别是在涉及异步处理时更需要这一步。继续讨论 MakeReservation 命令,其中一项要求是在分配特定资源之前需要所有者的批准。批准资源使用后,系统必须向用户发送确认信息。生成事件 ReservationApproved 时,模型中的通知开始运作。这个事件是另一条命令的结果,该命令应遵循我们之前描述的逻辑,但由不同的用户执行。


在设计中包含这一部分背后的想法是,除非获得批准,否则用户任务不会完成。同样,如果权限被拒绝,则领域可能需要还原部分更改。在设计系统时,我们必须考虑所有交互,直到用户的任务完成为止。

总结

业务规则是应用程序表达其对领域的了解的方式。正确构造业务规则有助于开发人员轻松理解代码,并应根据规则的职责将其分为不同类别。与此同时,使用结构化代码来表示用户任务可以减少开发团队需要理解的概念。因为业务规则取决于系统设计,所以解决方案架构师必须考虑设计支持它们的方式。


作者介绍:


Fabian Lopez 是佐治亚理工学院计算机科学硕士学位的软件工程师。目前,他在美洲开发银行担任解决方案架构师,设计烘焙行业的流程管理应用程序。Lopez 喜欢使用和创建软件模式,因为它为许多开发问题提供了解决方案参考。他定期参与用户研究,以识别用户模式并开发适合客户的解决方案。Lopez 注意到,许多好的技术解决方案失败了,因为用户在使用应用程序时陷入了迷茫,因而对解决方案的质量印象大减。


原文链接:


Using a DDD Approach for Validating Business Rules


2020-08-17 18:494954

评论

发布
暂无评论
发现更多内容

什么是服务器租用?

德胜网络-阳

6个JDK自带JVM调优工具,一次性打包给你说清楚

田维常

jvm调优

即将写入MySQL源码的官方bug解决之路

数据君

MySQL

区块链数字货币商城系统开发模式

薇電13242772558

区块链 数字货币

甲方日常 52

句子

工作 随笔杂谈 日常

2020双十一,阿里云GRTN拉开直播和RTC技术下半场的序幕

阿里云CloudImagine

架构 云直播 直播 流媒体 直播架构

Vokenization:一种比GPT-3更有常识的视觉语言模型

脑极体

厉害了!阿里内部都用的Spring+MyBatis源码手册,实战理论两不误

小Q

Java spring 学习 面试 mybatis

架构师第一期作业(第 9 周)

Cheer

作业

【JVM】肝了一周,吐血整理出这份超硬核的JVM笔记(升级版)!!

冰河

性能优化 内存模型 JVM 堆栈 JVM笔记

这份算法攻略,我拿到了5个大厂的offer

yes

面试 算法 笔试

揭秘双11:前端技术体系

大前端

adb的常用操作命令

Yolanda_trying

程序员如何判断跳槽岗位是否有坑!

Java架构师迁哥

《程序员面试金典》.pdf

田维常

面试

断供,危机or契机?开源商业化or社区化?后疫情下的开源路这样走 | 大咖对话

易观大数据

花四个月和阿里面试官“大战”7回合,成功将其“斩于马下”!复盘面试题及答案!

Java架构追梦

Java 阿里巴巴 面试 java架构

支撑2715​亿元海量订单 揭秘京东大促背后的数据库基石

京东科技开发者

数据库 数据仓库 云服务 云数据库

.net core增强工作流组件,基于稳定平台,多项目整合开发

雯雯写代码

程序员求助:腾讯面试题,64匹马8个跑道,多少轮选出最快的四匹

Java架构师迁哥

SQL数据库集合运算

正向成长

SQL表联结 SQL集合运算

Java中的线程与C++中的区别

jiangling500

Java c++ 线程

两句话给面试官讲清楚IOC

执墨

spring ioc 依赖倒置原则 springioc 控制反转

读完某C++神作,我只记住了100句话

MySQL从删库到跑路

c++

响应式关系数据库处理R2DBC

程序那些事

MySQL R2DBC 程序那些事 响应式系统 响应式数据库

Java中NullPointerException的完美解决方案

Silently9527

java8 Optional

有点意思的gif动图生成平台开发实战(二)

徐小夕

Java Vue 大前端 GIF React

直播卖货已成趋势

anyRTC开发者

音视频 WebRTC RTC

容器和虚拟机到底有啥区别?

网管

容器 虚拟机

程序员双十一剁手指南

数据君

腾讯云 程序员

超越竞争文化:致善式创新能否打造手机产业的“海法城”

脑极体

如何使用DDD方法验证业务规则_研发效能_Fabian Lopez_InfoQ精选文章