领域驱动系列:三种领域逻辑组织模式的本质
企业应用架构模式中明确提出了三种领域逻辑组织模式:事务脚本、领域模型和表模块。不少人看的云里雾里的,不少人说的似懂非懂的,主要原因是没有从项目的级别的分析和设计经验,只有单个项目模块的开发经验的人很难理解到位。
1.事务脚本:
事务脚本的理解其实最简单,但是很多人说不清,觉得比领域模型还难理解,也对应不到代码。但这只是幻觉,怎么可能最简单的领域逻辑模式都不懂,反而对最复杂的领域模型模式懂了呢。
我们看企业应用架构模式中强调的一句话"使用过程来组织领域逻辑",其实事务脚本就是从过程的角度看待需求,需求方和开发方在此阶段都热衷的核心是"这个功能是怎么个过程",二者达成一致后用代码去将这个粗糙的过程模拟出来。所以大多数人都在不自觉的应用事务脚本模式。简单说就是使用过程化的代码在模拟用户表面的需求。如果这个项目继续进行下去,那么问题来了:
(1)用户自己都不太清楚需求,需求肯定会随着用户的想法变化而不断变化。即使你作为需求方如果不仔细思考,只是简单的陈述下表面的流程,你也会经常性的由于自己偶尔的深入考虑或更没谱的想法而不断的变更需求。
(2)事务脚本模式的代码是过程式的,需要什么调用什么,常见的数据源通信、邮件服务、应用级别的日志安全等各种代码都混合在一起,如果需求变了,调整起来很困难。
这就是很多项目的一般状态,因为问题的根源在没有深入分析和理解用户的需求,所以不是用什么框架和分层,搞一些似是而非的实体或者采用了IOC和AOP等技术实现能起作用的的。还是要从根源上寻求解决之道,因此领域驱动设计强调通用语言,这样才能同需求人员一起对具体的领域进行深入的分析,这样的需求分析和模型设计具有更高的稳定性,才不会因为需求方的脑抽和风暴导致需求频发大幅度变化。
一旦你了解了事务脚本模式的核心,你就十分清楚事务脚本的适用范围:
(1)领域逻辑本身就是多个简单过程。
(2)需求十分简单,即使看起来表面化也已经足够深入。
在此提醒大家,要学习领域驱动设计千万别跑偏,不要忘记领域逻辑本身才是一切的分析和设计的根源。尤其是初学者千万不要把非领域层和应用层的各种框架技术和组件之类的混入到学习中。在分析和设计的过程中,至少要坚持两点:
(1)不要在此时关注表示层和数据源层
(2)尽量多从项目整体的角度看待问题,不要只以开发者的角度去思考。
事务脚本依然可以使用各种技术和框架,但无论你怎么命名文件和使用什么组件,依然是以过程来组织业务逻辑。以事务脚本模式组织领域逻辑的设计结果必然是以一系列的流程图为核心。
2.表模块:
表模块不再将过程作为组织领域逻辑的核心,而是将数据作为领域逻辑的核心。一些在深受事务脚本模式的毒害的团队可能意识到了过程的变化太不可预测了,而往往又不去或不能在需求分析上下功夫,因此从技术角度抓住了业务逻辑中相对过程更稳定的数据部分。也仅此而已。采用表模块的模式往往有以下两个结果:
(1)设计的结果主要是E-R图或披着类图皮的E-R图。
(2)自然的采用数据模型但坚持认为是领域模型。
也自然而然的得到表模块的适用范围:
(1)业务逻辑本身就是以数据为核心的简单处理。
(2)业务逻辑的流程十分简单,这点和事务脚本是一致的。
3.领域模型:
领域模型同时将行为和数据作为领域逻辑的核心。因此无法像事务脚本一样只关心过程和表面需求,也无法像表模块一样只关心数据。问题终于清晰了:
(1)事务脚本模式不(或逃避)深入分析需求。
(2)表模块强调了数据,得不到充分的领域模型。
(3)领域模型模式采用通用语言解决需求问题,采用过程和数据结合解决领域逻辑的组织。
实在是不能说的再复杂了,因为本质上的简单。由于领域逻辑本身的特性,往往会产生以下两种倾向的领域模型:
(1)形式上类似事务脚本模式的领域模型,这是由于领域逻辑本身的特性决定,即使从代码上看起来十分相似,但是具有更稳定和更少需求变动的优势。
(2)形式上类似表模块模式的领域模型。其他同上。
优势也是实在太明显了。我实在不能拒绝。这不是技术上的问题,这是需求分析和模型设计上的问题,我实在不能把这些简单的概念搞的更复杂了。在使用和不断完善通用语言的需求分析过程中,通过多次深入分析和迭代我们得到了比较稳定的需求分析,在完善设计的过程中,我们通过使用和识别出实体、值对象、领域服务和领域事件等概念,划分出聚合、子域、界限上下文来简化我们的设计。这是在以领域逻辑为核心的前提下,不断深入、细化和迭代的自然结果。
再次强调:
(1)DDD属于设计范畴而非实现范畴。
(2)DDD属于领域层的设计,别扯到架构和框架上。
(3)DDD的核心是通用语言和模型驱动设计。