【面向对象】DDD(一):传统开发模式 VS DDD 开发模式

article/2025/9/25 0:53:54

我们都知道,很多业务系统都是基于 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 类中
  • Dao + Entity(贫血):Entity主要用于数据库字段映射,若加入业务逻辑有被任意代码修改的风险

2.3 开发流程

领域驱动。

在这种开发模式下,我们需要事先理清楚所有的业务,定义领域模型所包含的属性和方法。领域模型相当于可复用的业务中间层。新功能需求的开发,都基于之前定义好的这些领域模型来完成。

我们知道,越复杂的系统,对代码的复用性、易维护性要求就越高,我们就越应该花更多的 时间和精力在前期设计上。而基于充血模型的 DDD 开发模式,正好需要我们前期做大量的 业务调研、领域模型设计,所以它更加适合这种复杂系统的开发。

2.4 代码示例

篇幅原因,代码示例详见下一篇文章…

3.总结

在这里插入图片描述

3.1 贫血模型比充血模型更受欢迎

面向过程编程风格有种种弊端,比如,数据和操作分离之后,数据本身的操作就不受限制了。任何代码都可以随意修改数据。既然基于贫血模型的这种传统开发模式 是面向过程编程风格的,那它又为什么会被广大程序员所接受呢?关于这个问题,下面三点原因:

  • 第一点原因是,大部分情况下,我们开发的系统业务可能都比较简单,简单到就是基于 SQL 的 CRUD 操作,所以,我们根本不需要动脑子精心设计充血模型,贫血模型就足以应 付这种简单业务的开发工作。除此之外,因为业务比较简单,即便我们使用充血模型,那模型本身包含的业务逻辑也并不会很多,设计出来的领域模型也会比较单薄,跟贫血模型差不 多,没有太大意义。
  • 第二点原因是,充血模型的设计要比贫血模型更加有难度。因为充血模型是一种面向对象的编程风格。我们从一开始就要设计好针对数据要暴露哪些操作,定义哪些业务逻辑。而不是 像贫血模型那样,我们只需要定义数据,之后有什么功能开发需求,我们就在 Service 层定 义什么操作,不需要事先做太多设计。
  • 第三点原因是,思维已固化,转型有成本。基于贫血模型的传统开发模式经历了这么多年, 已经深得人心、习以为常。你随便问一个旁边的大龄同事,基本上他过往参与的所有 Web 项目应该都是基于这个开发模式的,而且也没有出过啥大问题。如果转向用充血模型、领域驱动设计,那势必有一定的学习成本、转型成本。很多人在没有遇到开发痛点的情况下,是不愿意做这件事情的。

3.2 什么项目使用DDD开发模式

  • 基于贫血模型的传统的开发模式,比较适合业务比较简单的系统开发。
  • 基于充血模型的 DDD 开发模式,更适合业务复杂的系统开发。比如,包含各种利息 计算模型、还款模型等复杂业务的金融系统。

http://chatgpt.dhexx.cn/article/QrPsKx4f.shtml

相关文章

MVC开发模式

一.MVC设计模式 1.MVC模式&#xff08;Model-View-Controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&#xff0…

项目的开发模式

开发模式大概可以分为两种&#xff1a; 1、大公司的开发模式&#xff1b; 2、外包的开发模式&#xff1b; 一、大公司的开发模式&#xff1b; 1. 市场调研 2. 项目需求会&#xff08;人员&#xff09; 产品市场运营UI开发后端前端项目经理测试–>web/ios/安卓安全 3. …

什么是DDD开发模式

DDD尝试解决业务系统(逻辑CRUD)开发的复杂性问题&#xff0c;这种复杂性是由于复杂的业务规则&#xff0c;业务逻辑变化。 一般系统的业务逻辑、复杂性在于&#xff1a;流转判断多&#xff0c;专业规则多&#xff0c;计算量大。而DDD模式的解决的方式是通过分层&#xff0c;即业…

Scrum敏捷开发模式介绍与实践

文章目录 前言一、开发模式1. 瀑布流开发模式2. 迭代开发模式3. 螺旋开发模式4. 敏捷开发模式 二、敏捷开发模式三、敏捷模式1. Scrum2. Kanban3. XP4. Lean Startup 四、Scrum 敏捷开发模式1. 框架图2. 角色Scrum Master&#xff0c;SMProduct Owners&#xff0c; POSoftware …

什么是软件开发模式?

软件开发模式简介 1. 边做边改模型&#xff08;Build-and-Fix Model&#xff09; 好吧&#xff0c;其实现在许多产品实际都是使用的“边做边改”模型来开发的&#xff0c;特别是很多小公司产品周期压缩的太短。在这种模型中&#xff0c;既没有规格说明&#xff0c;也没有经过设…

T58 Office开发模式

加Check box https://www.howtogeek.com/204036/how-to-add-check-boxes-to-word-documents/ 点击设计模式激活。

C# 软件开发模式、设计模式、设计原则和架构

一、怎样做好软件开发&#xff1f; 软件是数据算法的集合体&#xff0c;是利用一定方法将数据进行合理的组合和分配的产物。其实在人们的生活当中&#xff0c;处处都充满着资源(数据)和方法(算法)&#xff0c;成功的人都是善于使用他们总结的方法来使用资源的。软件开发也不例外…

螺旋式开发模式

螺旋模型是一种演化 软件开发过程模型&#xff0c;它兼顾了 快速原型的 迭代的特征以及 瀑布模型的系统化与严格监控。螺旋模型最大的特点在于引入了其他模型不具备的风险分析&#xff0c;使软件在无法排除重大风险时有机会停止&#xff0c;以减小损失。同时&#xff0c;在每个…

常见的开发模式和不常见的开发模式

1. 瀑布式开发 瀑布模型的优点&#xff1a; 1、为项目提供了按阶段划分的检查点。 2、当前一阶段完成后&#xff0c;您只需要去关注后续阶段。 3、可在迭代模型中应用瀑布模型。增量迭代应用于瀑布模型。迭代1解决最大的问题。每次迭代产生一个可运行的版本,同时增加更多的…

软件开发的11种模式

软件开发的11种模式 1&#xff0c;边做边改模型&#xff08;Build-and-Fix-Model&#xff09; 在这种模型中&#xff0c;既没有规格说明&#xff0c;也没有经过设计&#xff0c;软件随着客户的需要一次又一次地不断被修改。在这个模型中&#xff0c;开发人员拿到项目立即根据…

常见的开发模式模式

前言 主要是了解常见的开发模式&#xff0c;从而理解测试贯穿在整个软件研发过程中的定位。 一、常见的开发模式 引用林子老师梳理的开发模式&#xff0c;主要包括以下几种&#xff1a; 测试流程通常跟软件开发流程紧密相关&#xff0c;需要基于开发流程来定义。基于企业不同…

云手机虚拟服务器地址和端口,手机服务器地址端口号

手机服务器地址端口号 内容精选 换一换 当后台重新配置邮箱服务器等信息后,手机端WeLink一定要退出重新登录一次。我们常用的邮箱,比如:QQ邮箱、163邮箱、腾讯企业邮箱、网易企业邮箱、263企业邮箱等常见邮箱,可以参考常见问题 > 客户端-邮件里的“常见的IMAP邮箱配置方…

使用正则表达式验证手机号码

使用正则表达式验证手机号码 开发工具与关键技术&#xff1a;VS2015、正则表达式 作者&#xff1a;易金亮 撰写时间&#xff1a;2019.07.07在项目中&#xff0c;总会涉及到数据的新增&#xff0c;比如新增用户信息等&#xff0c;而说到新增用户信息&#xff0c;就离不开用户的…

安卓搭建虚拟服务器,安卓手机搭建云服务器

安卓手机搭建云服务器 内容精选 换一换 本文介绍使用云手机服务时需要了解的基本概念。云手机是一台包含原生安卓操作系统,具有虚拟手机功能的云服务器,简单来说,云手机=云服务器+Android OS。您可以远程实时控制云手机,实现安卓APP的云端运行;也可以基于云手机的基础算力…

JS判断输入手机号码是否正确

JS判断输入手机号码是否正确 现在中国地区的号码 中国电信号段133、149、153、173、177、180、181、189、190、191、193、199 中国联通号段130、131、132、145、155、156、166、167、171、175、176、185、186、196 中国移动号段134(0-8)、135、136、137、138、139、1440、147、…

android qq账号登陆验证手机号码,注册QQ号如何跳过手机验证

QQ的安全性在逐步提高&#xff0c;而我们申请QQ的过程也越来越复杂了。许多用户不希望申请QQ时透露手机号码这类隐私信息。所以很少人使用需要手机验证的手机申请方式&#xff0c;所以电脑申请QQ成为主流&#xff0c;但电脑申请方式在申请过一次QQ号码之后(不论成功与否)就不能…

虚拟号码怎么开通?

虚拟码号的开通方式基本一样 一、首先是企业实名&#xff0c;上传企业的证明文件&#xff0c;法人证件。 二、然后是提出开号需求&#xff0c;号码数量&#xff0c;号码区域 三、然后缴纳费用 四、等待3-8个工作日开号 通过API或者SDK接口接入自己的系统&#xff0c;要不就…

自定义HorizontalScrollView嵌套HorizontalListView实现手势监听、按钮监听横向滚动功能

今日空闲花了点时间对以前自主实现的项目功能进行改进和优化&#xff0c; 其实一些界面的小功能有时候没实现过&#xff0c;也没经验类似项目功能经验&#xff0c;反而耗费的时间会更多。下面我所描述的界面功能就是我在对用RecyclerView控件不熟悉的情况下使用了HorizontalScr…

ScrollView/HorizontalScrollView常用技巧,附源码

ScrollView是ViewGroup的派生类&#xff0c;ViewGroup是View的派生类。 屏幕大小总是有限制的&#xff0c;对移动设备来说更是如此。当有很多内容需要显示的时候&#xff0c;一屏显示不完时&#xff0c;就需要使用滚动的方式。 ScrollView只能包含一个直接子vi…

Android 自定义 HorizontalScrollView 横向滑动效果

自从Gallery被谷歌废弃以后&#xff0c;Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果。的确HorizontalScrollView可以实现Gallery的效果&#xff0c;但是HorizontalScrollView存在一个很大的问题&#xff0c;如果你仅是用来展示少量的图片&#xff0c;应…