许多开发者在项目中希望能够使用 DDD 原因在于能够管理业务的复杂度,避免在业务规则愈发复杂的情况下代码以及架构发生腐化,最终变的难以维护。系统复杂度体现在多个层面,例如繁琐的流程,繁复的校验规则,数据的多样性等,DDD 对于不同层面的复杂度提供了不同的应对模式,今天的文章会聚焦与如何使用 Specification 模式解决「业务规则」相关的复杂性。
业务规则
在介绍 Specification 模式之前,我们先明确一下什么是「业务规则」。作为一个开发者,以下的这些一定是你日常工作中常见的工作。
- 校验业务对象的某些状态是否合法,例如当前账户是否启用,账户余额是否充足,事故日期是否在保险单的有效时间内。
- 从业务对象的集合中筛选出符合条件的结果集,例如从用户的交易记录中找出购买打折产品的记录。
- 检查一个新创建的业务对象是否符合某些业务条件,例如一张新创建的订单,它对应的客户与商户都应该是合法系统用户。
为了方便后续的讨论,我们将业务规则的概念窄化为以上三种类型。接下来的问题是这些业务规则在系统中是如何实现的?
最原始的方法是编写了许多小方法实现这些校验或是筛选逻辑,分散在各个 Domain Service 类中。这样做的缺点很明显,其一是难以管理,当业务规则越来越多时,这些散落在各处的方法就无法复用,而开发人员也没有办法集中的管理这些方法。其二是丢失了业务知识,这些方法大部分都很短小,简单,但是这些规则其实包含了大量的业务知识,如果任其分散在不同的 Domain Service 中,后续的开发过程中就很容易丢失这些业务知识。
在此基础上的另一个方案也是实际项目中使用比较多的,即编写各种