程序员架构师成长记

领域驱动设计与开发实践(2)【翻译】

2016-07-02  本文已影响133人  华子闲话

简单的应用

      本文使用的是一个简单的家庭借贷处理系统,业务用例是审批一个家庭借贷(抵押借贷)的资金请求。当提交一个资金申请到抵押借贷公司,请求首先经过保险流程,核保人员根据用户的收入详情,信用记录和其它因素批准或者拒绝贷款请求。如果资金申请审批通过,它将通过借贷审批流程的关闭和出资过程。

      借贷处理系统的出资模块自动把出资支付款的流程发给借款人。一个典型的出资流程是从抵押放贷者(银行)开始,转发借贷文件到一个债券公司。债券公司然后重新审查借贷文件并且与卖方和买方约定时间关闭这个借贷。借款方和卖方在产权公司同意关闭贷款并签署文件移交资产。

架构

      典型的企业应用架构包含下面4个概念层:

·用户层(展示层):负责展示信息和解释用户的命令

·应用层:这层协调应用的活动。它不包含任何业务逻辑。它不持有任何业务对象的状态,但是持有任何应用任务流程的状态。

·领域层:这层包含业务领域的信息,业务对象的状态在这里。业务对象的持久化和它们的状态委托给基础框架。

·基础架构层:这层为其它层提供支持。它提供了层之间的通信,实现了业务对象的持久化,包含用户层的支持库等等。

让我们更详细地了解一下应用层和领域层。应用层:

·负责在应用程序内用户界面见的导航,与其它系统的应用层交互

·在将用户输入数据传输给应用的低层时,进行基本的验证(与业务逻辑无关的验证)

·不包含任何与业务或领域相关的逻辑或数据访问逻辑

·没有任何反应业务用例的状态,但是管理用户会话的状态或者任务的处理状态。

领域层:

·负责业务领域的概念,关于业务用例和业务规则。领域对象封装了业务对象的状态和行为。一个贷款处理系统的业务实体的例子有抵押,资产和借款人。

·如果一个用例跨多个用户请求 (例如:贷款注册过程包含多个步骤:用户输入贷款详情,系统基于贷款参数返回产品和利率,用户选择一个特定的产品/利率组合,最终系统在这个利率上锁定这次贷款),它也管理这个业务用户的状态(会话)。

·包含服务对象——它们仅仅有一个定义的好的操作行为,这个行为不属于任何领域对象。服务封装了不适合领域对象自身的业务领域的行为。

·是业务应用的核心,并且应该与应用的其它层很好的隔离。同时,它也不应该依赖于在其它层使用的框架。

图2展示了应用中使用的框架层以及它们怎么与DDD相关联。

下面的设计方面被认为是当前DDD实现方法的主要元素:

·面向对象编程(OOP)

·依赖注入(DI)

·面向切面编程(AOP)

(此处省略OOP,DI,AOP的翻译段落)

业务规则

      业务规则是业务领域的重要部分。它们定义了数据的有效性和其它需要在特定业务处理流程中附加到领域对象的约束。业务规则典型的分为以下类型:

·数据校验

·数据转换

·业务决策

·流程路由(工作流逻辑)

      在真实的DDD世界,上下文是非常重要的。上下文特征指明了领域对象和其它运行时因素的协调例如什么业务规则需要使用等等。校验和其它业务规则一直在一个特定上下文中被处理。这意味着同一个领域对象,在不同的上下文中,将会处理不同的业务规则。举个例子,一个贷款领域对象的一些属性(如贷款金额和利率)在已经通过审批流程的核保步骤后不能被修改。但是相同的属性在贷款刚刚注册并且在一个指定利率锁定下可以被修改。

      虽然所有领域特定业务规则都应该被封装在领域层,但是有些应用设计方法把规则放到外观类(façade classes)中,对于业务规格来说这导致领域类变成了“贫血性”。在小规模应用程序中,这可以被接受的,在中大型包含复杂业务规则的应用这种方法不推荐使用。更好的设计选择是把规则放到属于应该属于的领域对象中。如果一个业务规则逻辑跨2个或多个实体对象,那么它应该属于一个服务类的一部分。

      同时,如果我们对应用不是很勤奋,设计业务规则将最终已很多开关语句的形式被编码。随着时间业务规则变得更加复杂,开发人员没有花时间重构代码把开关语句改为更加可管理的设计。代码中硬编码的复杂路由逻辑或者决策规则导致更长的方法体,重复代码,和一个僵硬的应用设计,终究成为一个维护的噩梦。一个好的设计是把所有规则(尤其是复杂规则——随着业务策略变动而经常改变的规则)放到一个规则引擎中(使用一个规则框架像JBoss Rules,OpenRules,或者Mandarax)并且在领域对象中触发它。

      验证规则常常使用不同的语言实现像javascript,XML,Java code,和其它脚本语言。但是由于业务规则的动态天性,如Ruby,Groovy,或者Domain Specific Language(DSL)是更好的选择去定义和管理规则。Structs(应用层),Spring(服务)和Hibernate(ORM)都有它们自己的验证模块,我们可以在这里对进来和出去的数据对象使用验证。在一些场景下,验证规则也能被切面(Aspect)管理,它们能够编入硬功的不能层(例如服务层和控制器)。

      重要的是在写领域类管理业务逻辑时牢记单元测试。任何规则逻辑的改变应该很容易在隔离下进行单元可测试。

      这个简单应用包含了一些业务规则,验证贷款参数在允许的产品和利率规格。规则使用脚本语言(Groovy)定义并且应用在传给FundingService对象的贷款数据上。

原文链接:Domain Driven Design and Development In Practice

上一篇下一篇

猜你喜欢

热点阅读