【面向对象】DDD(一):传统开发模式 VS DDD 开发模式
我们都知道,很多业务系统都是基于 MVC 三层架构来开发的。实际上,更确切点讲,这是一种基于贫血模型的 MVC 三层架构开发模式。虽然这种开发模式已经成为标准的 Web 项目的开发模式,但它却违反了面向对象编程风格,是一种彻彻底底的面向过程的编程风格,因此而被有些人称为反模式(antipattern)。
特别是领域驱动设计(Domain Driven Design,简称 DDD)盛行之后,这种基于贫血模型的传统的开发模式就更加被人诟病。而基于充血模型的 DDD 开发模式越来越被人提倡。
MVC架构(大前提)
MVC 三层开发架构是一个比较笼统的分层方式,落实到具体的开发层面,很多项目也并不会 100% 遵从 MVC 固定的分层方式,而是会根据具的项目需求,做适当的调整。
现在很多 Web 或者 App 项目都是前后端分离的,后端负责暴露接口给前端调用。 这种情况下,我们一般就将后端项目分为 Repository 层、Service 层、Controller 层。其中,Repository 层负责数据访问,Service 层负责业务逻辑,Controller 层负责暴露接口。当然,这只是其中一种分层和命名方式。不同的项目、不同的团队,可能会对此有所调整。不过,万变不离其宗,只要是依赖数据库开发的 Web 项目,基本的分层思路都大差不差。
V :View(展示层):HTML
C(#) :Controller(逻辑层)
- Controller : 前端交互,暴露接口 ↑
- Service(#) :核心业务逻辑
- Dao :数据库交互,数据存取 ↓
M : Model(数据层):MySQL
1.传统开发模式(贫血模型)
1.1 贫血模型
数据与逻辑分离 --> 面向过程编程
1.2 传统开发模式
分层模型(全贫)
- Controller + VO
- Service + BO 完全数据逻辑隔离,~O只做数据结构;破坏了面向对象封装特性,是典型面向过程的编程风格
- Dao + Entity
1.3 开发流程
SQL驱动
我们接到一个后端接口的开发需求的时候,就去看接口需要的数据对应到数据库中,需要哪张表或者哪几张表,然后思考如何编写 SQL 语句来获取数据。
之后就是定义 Entity、BO、VO, 然后模板式地往对应的 Repository、Service、Controller 类中添加代码。业务逻辑包裹在一个大的 SQL 语句中,而 Service 层可以做的事情很少。
SQL 都是针对特 定的业务功能编写的,复用性差。当我要开发另一个业务功能的时候,只能重新写个满足新需求的 SQL 语句,这就可能导致各种长得差不多、区别很小的 SQL 语句满天飞。
所以,在这个过程中,很少有人会应用领域模型、OOP 的概念,也很少有代码复用意识。 对于简单业务系统来说,这种开发方式问题不大。但对于复杂业务系统的开发来说,这样的 开发方式会让代码越来越混乱,最终导致无法维护。
1.4 代码示例
// Controller+VO(View Object) //
public class UserController { private UserService userService; // 通过构造函数或者 IOC 框架注入 public UserVo getUserById(Long userId) { UserBo userBo = userService.getUserById(userId); UserVo userVo = [...convert userBo to userVo...]; return userVo; }
}
// 单纯存储数据的数据结构
public class UserVo {// 省略其他属性、get/set/construct 方法private Long id;private String name; private String cellphone;
}// Service+BO(Business Object) //
// 业务逻辑都在Service中
public class UserService {private UserRepository userRepository; // 通过构造函数或者 IOC 框架注入 public UserBo getUserById(Long userId) { UserEntity userEntity = userRepository.getUserById(userId); UserBo userBo = [...convert userEntity to userBo...]; return userBo; }
}
// BO只存储数据,无业务逻辑
public class UserBo {// 省略其他属性、get/set/construct 方法private Long id; private String name; private String cellphone;
}// Repository+Entity //
public class UserRepository { public UserEntity getUserById(Long userId) { //... }
}
public class UserEntity {// 省略其他属性、get/set/construct 方法 private Long id;private String name; private String cellphone;
}
2.DDD 开发模式(充血模型)
2.1 充血模型:
领域模型(Domain)处理大部分逻辑,Service只做少部分逻辑 --> 数据逻辑融合 --> 面向对象编程
2.2 DDD开发模式
分层模型(贫+充)
- Controller + VO(贫血):因为VO是作前端传输数据载体,不应该有逻辑
- Service < Domain(领域模型)
- Service 类负责与 Dao 交流
- 将Entity转化为Domain,由 Domain(领域模型)完成大部分业务逻辑
- 保证Domain不与其他层(Dao…)或框架(Spring…) 耦合在一起
- Service 类负责跨领域模型的业务聚合功能。
- Service 类负责一些非功能性及与三方系统交互的工作。比如幂等、事务、发邮件、发消 息、记录日志、调用其他系统的 RPC 接口等,都可以放到 Service 类中
- Service 类负责与 Dao 交流
- Dao + Entity(贫血):Entity主要用于数据库字段映射,若加入业务逻辑有被任意代码修改的风险
2.3 开发流程
领域驱动。
在这种开发模式下,我们需要事先理清楚所有的业务,定义领域模型所包含的属性和方法。领域模型相当于可复用的业务中间层。新功能需求的开发,都基于之前定义好的这些领域模型来完成。
我们知道,越复杂的系统,对代码的复用性、易维护性要求就越高,我们就越应该花更多的 时间和精力在前期设计上。而基于充血模型的 DDD 开发模式,正好需要我们前期做大量的 业务调研、领域模型设计,所以它更加适合这种复杂系统的开发。
2.4 代码示例
篇幅原因,代码示例详见下一篇文章…
3.总结
3.1 贫血模型比充血模型更受欢迎
面向过程编程风格有种种弊端,比如,数据和操作分离之后,数据本身的操作就不受限制了。任何代码都可以随意修改数据。既然基于贫血模型的这种传统开发模式 是面向过程编程风格的,那它又为什么会被广大程序员所接受呢?关于这个问题,下面三点原因:
- 第一点原因是,大部分情况下,我们开发的系统业务可能都比较简单,简单到就是基于 SQL 的 CRUD 操作,所以,我们根本不需要动脑子精心设计充血模型,贫血模型就足以应 付这种简单业务的开发工作。除此之外,因为业务比较简单,即便我们使用充血模型,那模型本身包含的业务逻辑也并不会很多,设计出来的领域模型也会比较单薄,跟贫血模型差不 多,没有太大意义。
- 第二点原因是,充血模型的设计要比贫血模型更加有难度。因为充血模型是一种面向对象的编程风格。我们从一开始就要设计好针对数据要暴露哪些操作,定义哪些业务逻辑。而不是 像贫血模型那样,我们只需要定义数据,之后有什么功能开发需求,我们就在 Service 层定 义什么操作,不需要事先做太多设计。
- 第三点原因是,思维已固化,转型有成本。基于贫血模型的传统开发模式经历了这么多年, 已经深得人心、习以为常。你随便问一个旁边的大龄同事,基本上他过往参与的所有 Web 项目应该都是基于这个开发模式的,而且也没有出过啥大问题。如果转向用充血模型、领域驱动设计,那势必有一定的学习成本、转型成本。很多人在没有遇到开发痛点的情况下,是不愿意做这件事情的。
3.2 什么项目使用DDD开发模式
- 基于贫血模型的传统的开发模式,比较适合业务比较简单的系统开发。
- 基于充血模型的 DDD 开发模式,更适合业务复杂的系统开发。比如,包含各种利息 计算模型、还款模型等复杂业务的金融系统。
【面向对象】DDD(一):传统开发模式 VS DDD 开发模式相关推荐
- MVC模式和DDD模式对比,谁才是银弹?
目录 MVC模式和DDD模式对比,谁才是银弹? 从DDD的角度看MVC架构的问题 第一层:初出茅庐 第二层:草船借箭(战术设计) 第三层:运筹帷幄(战略设计) DDD的不足 总结 MVC模式和DDD模 ...
- 嵌入式开发中使用DDD进行调试
在嵌入式程序开发过程中,程序员要进行大量的调试,以此验证程序的正确性,修改潜在的错误.调试器对于程序员来说是不可或缺的必备工具.在Linux环境中,有很多调试工具和调试辅助工具,例如GDB.XXGDB ...
- 微信小程序——传统开发模式与云开发模式对比
目 录 1.传统开发模式与云开发模式的对比图 2.云开发技术能力说明 3.云开发技术特点 1.传统开发模式与云开发模式的对比图 通过传统开发模式与云开发模式的对比图可以看出传统开发模式需要开发者关注 ...
- 低代码平台只是改变传统开发的模式,为什么开发人员对它好感度不高
低代码开发平台已经成为很多企业开发软件的首选方式,主要是因为低代码开发平台可以提高开发的效率,减少代码的编写数量,帮助企业减轻对专业技术人员的依赖,降低软件开发的成本.虽然低代码平台是大势所趋,但是很 ...
- DDD 领域驱动设计-如何 DDD?
注:科比今天要退役了,我是 60 亿分之一,满腹怀念-??? 前几天看了园友的一篇文章<我眼中的领域驱动设计>,文中有段话直击痛点:有人误认为项目架构中加入 Repository,Doma ...
- [外文理解] DDD创始人Eric Vans:要实现DDD原始意图,必须CQRS+Event Sourcing架构。
原文:http://www.infoq.com/interviews/Technology-Influences-DDD# 要实现DDD(domain drive design 领域驱动设计)原始意 ...
- Lind.DDD敏捷领域驱动框架~Lind.DDD各层介绍
回到目录 Lind.DDD项目主要面向敏捷,快速开发,领域驱动等,对于它的分层也是能合并的合并,比之前大叔的框架分层更粗糙一些,或者说更大胆一些,在开发人员使用上,可能会感觉更方便了,更益使用了,这就 ...
- 『设计模式』Web程序开发最基本的编程模式--MVC编程模式
23种设计模式+额外常用设计模式汇总 (持续更新) 什么是MVC编程模式 ? MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controlle ...
- 【华为云实战开发】16.DevOps交付模式下的软件测试
文:华为云DevCloud 兵东 众所周知,近10年IT领域有两个关键的风向转变,传统IT向云计算转变,传统瀑布和迭代开发模式向敏捷开发模式转变.这两个转变促成了DevOps产品交付模式的出现.互联 ...
- 面向对象测试与传统软件测试有何异同,面向对象软件测试与传统测试有何区别...
由于面向对象技术具有封装.继承.多态等新的特性,带来了传统程序设计所不存在的错误,导致原来行之有效的软件测试技术对面向对象技术开发的软件有些力不从心. 面向对象软件测试与传统软件测试有以下不同: 测试 ...
最新文章
- KINDLE TOUCH修复板砖过程
- Android中CardView的简单使用
- 利用.swp文件恢复源文件
- windows与虚拟机中的Ubuntu共享文件夹
- OpenGL基础12:进入3D世界
- css3位移过度效果,详解Css3新特性应用之过渡与动画
- python画立体心形折纸图解_立体的心形盒子的折纸图解过程
- 2021 年系统分析师下午真题及答案
- win10 Matlab2017a .m相关文件关联
- 面试之MySQL调优问题
- 1.4多媒体计算机系统教案,1.4 多媒体计算机系统教案3
- oracle设置查看格式,Oracle 设置显示格式
- 解决Referenced file contains errors
- 2020移动apn接入点哪个快_最新联通上网卡APN的设置方法
- 马建威android视频,5.25春季班高级班第三期第五节课课堂总结
- 牛逼啊!一顿火锅钱+一台旧手机 = 自主导航机器人?
- Security:如何安装 Elastic SIEM 和 EDR
- 构建静态页面 之 [ 浮动 ]
- 逻辑思维训练——排除法
- 用计算机模拟股票大盘,股票模拟盘操作与实盘不同之处有哪些
热门文章
- limesurvey_LimeSurvey简介:一个开源,功能丰富的轮询平台
- 《高等代数学》读书笔记前言
- Python之计算机算法基础总结(借鉴、整理)、排序算法、查找算法
- 应用随机过程概率模型导论(9th 英文版) Sheldon M.Ross 共享
- 调试器---镜像劫持
- keras实现手写字体识别
- php版wap浏览器,PHP 检测手机浏览器的代码
- 怎么查看计算机办公软件版本的,怎样查看电脑用的什么办公软件
- Microsoft Visio 2003下载地址
- 异常信息:Unable to update index for aliyun|http://maven.aliyun.com/nexus/content/groups/public/ 解决方法