写点什么

如何使用 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:494978

评论

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

SpringCloud 从入门到精通 09--- 支付服务集群

Felix

求职阿里Java 技术岗位的经历,三轮技术面+HR面,面试也不过如此

Java架构之路

Java 程序员 架构 面试 编程语言

专科出身Java开发,2年进入苏宁,5年跳槽阿里,我晋升这么快的秘诀是什么?

Java架构追梦

Java 阿里巴巴 面试 架构师 成长路线

SpringCloud 从入门到精通 08--- Eureka集群

Felix

从根上理解高性能、高并发(四):深入操作系统,彻底理解同步与异步

JackJiang

网络编程 高并发 高性能 即时通讯

Dubbo 版 Swagger 来啦!Dubbo-Api-Docs 发布

阿里巴巴云原生

Java 云原生 dubbo 大前端 中间件

华为云张昆:支持全场景全业务,GaussDB加速企业数字化转型

华为云开发者联盟

数据库

Mobileye的创新科技与方案将助力自动驾驶汽车畅行世界、惠及大众

E科讯

毕业三年,从小公司到大厂,先后四面阿里、小米、美团等,终于收到offer!

Java架构之路

Java 程序员 架构 面试 编程语言

重学JS | 异步编程 Promise

梁龙先森

大前端 编程语言 28天写作

区块链即时通讯系统开发方案,IM聊天社交软件开发

v16629866266

Spring中@Import的作用

张健

面向对象之魔术方法· 第1篇《__init__方法,__new__方法》

清菡软件测试

测试

阿里开发7年大牛:闭关60天学懂NDK+Flutter,大厂面试题汇总

欢喜学安卓

android 程序员 面试 移动开发

安卓开发详解!Flutter全方位深入探索,吊打面试官系列!

欢喜学安卓

android 程序员 面试 移动开发

Alluxio Day 2021 线上直播

腾讯云大数据

大数据

第九周作业

dll

连续三年蝉联第一,Flink 荣膺全球最活跃的 Apache 开源项目

Apache Flink

Apache flink

【设计模式】断路器模式

soolaugust

设计模式 28天写作

sync.singleflight 到底怎么用才对?

cyningsun

并发 Concurrency singleflight Cache Miss Go 语言

再谈跨界 互联网+的建筑行业

张老蔫

28天写作

CSS12 - 清除浮动

Mr.Cactus

html/css

用技术的方式,在UI设计稿中设置随机码,保证高清

行者AI

Python

即构推出低延迟直播产品L3,可将直播延迟降到1s

ZEGO即构

对于我们程序员来说,基本面是什么呢?

Java架构师迁哥

WireMock 使用

hungxy

测试 WireMock

week8-homework

J

量化自动交易系统开发,量化炒币

薇電13242772558

数字货币 策略模式

波场链智能合约软件开发|波场链智能合约APP系统开发

系统开发

程序员的五年:双非学历,两年进入苏宁,五年跳槽到阿里,建议收藏!

996小迁

Java 架构 面试 JVM Spring全家桶

真是太刺激了!美团CTO五轮面试,Java岗高级工程师一二三四五面面经(已拿到offer)

Java架构之路

Java 程序员 架构 面试 编程语言

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