引言:
业务开发常用的基于贫血模型的MVC架构违背OOP吗?
MVC三层架构是一种基于贫血模型的开发模式, 虽然已经成为标准的web开发模式, 但它违反了面向对象编程风格, 是一种面向过程编程风格, 被人称为: 反模式
当领域驱动设计(Domain Driven Design, 简称DDD)盛行后, 传统的开发模式更加被人诟病. 下面结合"虚拟钱包"的开发案例, 来弄清楚这2种开发模式
本节需要搞清楚下面几个问题
- 什么是贫血模型? 什么是充血模型?
- 为什么基于贫血模型的传统开发模式违反的OOP?
- 基于贫血模型的传统开发模式既然违反了OOP, 那又为什么如此流行?
- 什么情况下我们应该考虑使用基于充血模型的DDD开发模式?
一. 什么是基于贫血模型的传统开发模式?
1.1 回顾MVC三层架构
MVC三层架构中的M标识Model, V表示View, C表示Controller. 它将整个项目分为三层: 展示层, 逻辑层, 数据层. 在前后端分离的项目中, 后端一般分别为: Repository层, Service层, Controller层.
1.2 什么是贫血模型?
平时开发web后端项目时, 由UserEntity和UserRepository组成数据访问层, UserBO和UserService组成业务逻辑层, UserVO和UserController组成接口层.
我们可以发现UserBO是一个纯粹的数据结构, 里面只包含数据, 不包含任何业务逻辑, 业务逻辑都集中在UserService中. Service层的数据和业务被分割为: BO和Servcie, 那么像这种只包含数据, 不包含业务逻辑的类就叫做: 贫血模型(Anemic Domain Model).
这种破坏了面向对象的封装特性, 是一种典型的面向过程的编程风格.
二. 什么是基于充血模型的DDD开发模式?
目前它是一种被推崇的开发模式
2.1 什么是充血模型?
在贫血模型中, 数据和业务是分散在2个不同的类中, 充血模型(Rich Domain Model)正好相反, 数据和业务逻辑被封装在一个类中, 满足面向对象的封装特性, 是一种典型的面向对象编程风格.
2.2 什么是领域驱动设计?
领域驱动设计: 即DDD, 主要用来指导如何解耦业务系统, 划分业务模块, 定义业务领域模型及交互.
在基于贫血模型的传统开发模式中, Service层包含Service类和BO类两部分, BO是贫血模型, 只包含数据, 不包含业务逻辑, 业务逻辑都集中在Service类中.
在基于充血模型的DDD开发模式中, Service层包含Service类和Domain类两部分, Domain相当于BO, 不过跟BO不同的是, Domain既包含数据, 也包含业务逻辑, 而Service类变得非常单薄
总结:
(1) 基于贫血模式的开发模式, 重Service, 轻BO; (2) 基于充血模式的开发模式, 重Domain, 轻Service;
三. 为什么基于贫血模型的传统开发模式如此受欢迎?
- 大部分情况下, 系统业务比较简单, 不需要精心设计充血模型, 贫血模型就足以应付
- 充血模型比贫血模型更加有难度, 需要设计好对数据的暴露, 定义好业务逻辑等
- 思维固化, 转型需要成本.
四. 什么项目应该考虑使用基于充血模型的DDD开发模式?
基于贫血模型的传统开发模式, 适合业务简单的系统开发.
基于充血模型的DDD开发模式, 适合业务复杂的系统开发.
它们俩除了一个是业务放在service层中, 一个业务放在Domain领域模型中, 还是一个非常重要的区别, 就是开发模式.
基于DDD的开发模式, 首先要理清所有的业务, 才能定义领域模型中所包含的属性和方法.日后维护起来, 都在各自的领域模型中, 可维护性更高.所以越复杂的系统更适合充血模型的DDD开发模式.
五.课堂讨论
- UserEntity, UserBo, UserVO包含的字段都差不多, 是否可以合并为一个类呢?
不行, 各层之间的数据模型不要共用, 因为各自的稳定性不同.各层数据模型变更原因和速率都不同, 离IO设备越近, 稳定性越差. 比如说: controller层的VO, rep层的entity. Domain层的数据稳定性是最高的.