领域驱动设计(DDD)与MVC架构:理念对比与架构选择
领域驱动设计(DDD)与MVC架构:理念对比与架构选择
一、架构之争的本质:业务复杂度驱动技术演进
在软件开发领域,没有银弹式的完美架构,只有适合当前业务场景的合理选择。MVC与DDD的区别本质上是业务复杂度与架构响应能力的匹配问题。让我们通过一个真实案例展开思考:
案例背景
某金融科技公司初期采用MVC架构开发支付系统,随着业务扩展,新增跨境支付、分账系统、风控规则等功能后,代码库逐渐演变成"大泥球"架构,最终耗时6个月重构为DDD架构。
这个案例揭示了架构选型的核心原则:业务复杂度决定架构深度。
二、MVC架构:轻量级的技术分层典范
1. 核心三要素
- Model:数据模型(如数据库表结构)
- View:用户界面(如JSP/Thymeleaf模板)
- Controller:业务逻辑协调器(如Spring MVC的@Controller)
2. 典型代码结构
// Model
@Entity
public class Order {@Idprivate Long id;private BigDecimal amount;
}// Controller
@RestController
public class OrderController {@Autowiredprivate OrderService service;@PostMapping("/orders")public String createOrder(OrderDTO dto) {return service.createOrder(dto);}
}// Service
@Service
public class OrderService {@Transactionalpublic String createOrder(OrderDTO dto) {Order order = new Order();order.setAmount(dto.getAmount());orderRepository.save(order);return "success";}
}
3. 适用场景
- 简单CRUD应用(后台管理系统)
- 快速原型验证
- 业务逻辑密度低的展示型网站
三、DDD架构:复杂业务系统的破局之道
1. 战略设计核心模式
| 模式 | 作用 | 示例 |
|---|---|---|
| 限界上下文 | 业务能力单元边界 | 支付上下文 vs 风控上下文 |
| 上下文映射 | 跨上下文协作模式 | 防腐层(ACL)、共享内核 |
| 统一语言 | 消除业务与技术术语鸿沟 | 将"用户"统一为"Customer" |
2. 战术设计核心要素
// 聚合根
public class Order implements AggregateRoot<OrderId> {private OrderId id;private List<OrderItem> items;public void addItem(Product product, int quantity) {if (quantity > product.getStock()) throw new BusinessException("库存不足");items.add(new OrderItem(product, quantity));}
}// 领域服务
@Service
public class PaymentService {public PaymentResult pay(Order order, PaymentMethod method) {// 支付策略选择PaymentStrategy strategy = strategyFactory.getStrategy(method);return strategy.execute(order);}
}// 领域事件
public class OrderPaidEvent {private OrderId orderId;private LocalDateTime paidTime;
}
3. 分层架构演进
# 传统MVC分层
- controller/
- service/
- dao/# DDD分层
+ interfaces/ # 适配层(API/RPC/消息监听)
+ application/ # 应用服务(用例编排)
+ domain/ # 领域模型(聚合根/领域服务)
+ infrastructure/ # 基础设施(DB/缓存实现)
四、MVC与DDD的六大核心差异
| 维度 | MVC | DDD |
|---|---|---|
| 设计目标 | 技术关注点分离 | 业务复杂性治理 |
| 核心要素 | Model-View-Controller | 限界上下文/聚合根/领域事件 |
| 代码组织 | 按技术层级划分 | 按业务能力划分 |
| 数据建模 | 数据库驱动(贫血模型) | 业务驱动(充血模型) |
| 业务逻辑位置 | 分散在Service层 | 内聚在Domain层 |
| 扩展成本 | 高(牵一发动全身) | 低(限界上下文隔离) |
五、架构选型决策树
决策依据:
- 业务规则超过50条 → 考虑DDD
- 领域专家深度参与 → 推荐DDD
- 预期3年以上生命周期 → 必须DDD
六、混合架构实践建议
对于过渡期项目,可采用 “MVC外壳+DDD内核” 策略:
-
初期:在Service层引入领域模型
@Service public class OrderService {// 传统Service方法public void createOrder(OrderDTO dto) {// 转换为领域模型Order order = new Order(dto);orderRepository.save(order);} } -
中期:逐步拆分出Domain层
-
后期:建立完整分层架构
七、从MVC到DDD的重构收益
某电商平台重构前后对比:
| 指标 | 重构前(MVC) | 重构后(DDD) | 提升幅度 |
|---|---|---|---|
| 需求交付周期 | 2周 | 3天 | 80% |
| 生产缺陷率 | 0.5% | 0.08% | 84% |
| 新成员上手时间 | 1个月 | 2周 | 50% |
结语:架构的本质是管理复杂性
MVC如同瑞士军刀,轻便灵活但功能有限;DDD则是专业手术刀,精准解决复杂问题。架构选型的最高境界是:用最简单的架构解决当前问题,同时为未来演进留好扩展点。
相关文章:
领域驱动设计(DDD)与MVC架构:理念对比与架构选择
领域驱动设计(DDD)与MVC架构:理念对比与架构选择 一、架构之争的本质:业务复杂度驱动技术演进 在软件开发领域,没有银弹式的完美架构,只有适合当前业务场景的合理选择。MVC与DDD的区别本质上是业务复杂度与…...
牛客周赛:84:B:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scanner new Scanner(S…...
【理想解法学习笔记】
目录 理想解法原理简介算法步骤属性值规范化方法代码示例 理想解法 原理简介 TOPSIS(Technique for Order Preference by Simi larity to IdealSolution)法是一种逼近理想解的排序方法。其基本的处理思路是:首先建立初始化决策矩阵,而后基于规范化后的初…...
CI/CD—Jenkins配置一次完整的jar自动化发布流程
背景: 实现设想: 要创建自动化发布,需要准备一台测试服务器提前安装好java运行所需的环境,JDK版本最好和Windows开发机器上的版本一致,在Jenkins上配置将构建好的jar上传到测试服务器上,测试服务器自动启动…...
Magento2根据图片文件包导入产品图片
图片包给的图片文件是子产品的图片,如下图:A104255是主产品的sku <?php/*** 根据图片包导入产品图片,包含子产品和主产品* 子产品是作为主图,主产品是作为附加图片*/use Magento\Framework\App\Bootstrap;include(../app/boot…...
从零开始的python学习(五)P71+P72+P73+P74
本文章记录观看B站python教程学习笔记和实践感悟,视频链接:【花了2万多买的Python教程全套,现在分享给大家,入门到精通(Python全栈开发教程)】 https://www.bilibili.com/video/BV1wD4y1o7AS/?p6&share_sourcecopy_web&v…...
OpenHarmony5.0分布式系统源码实现分析—软总线
一、引言 OpenHarmony 作为一款面向万物互联的操作系统,其分布式软总线(Distributed SoftBus)是实现设备间高效通信和协同的核心技术之一。分布式软总线通过构建一个虚拟的总线网络,使得不同设备能够无缝连接、通信和协同工作。本…...
基于SpringBoot实现旅游酒店平台功能六
一、前言介绍: 1.1 项目摘要 随着社会的快速发展和人民生活水平的不断提高,旅游已经成为人们休闲娱乐的重要方式之一。人们越来越注重生活的品质和精神文化的追求,旅游需求呈现出爆发式增长。这种增长不仅体现在旅游人数的增加上࿰…...
代码随想录算法训练营第六十一天 | 108. 冗余连接 109. 冗余连接II
108. 冗余连接 题目链接:KamaCoder 文档讲解:代码随想录 状态:AC Java代码: import java.util.*;class Main {public static int[] father;public static void main(String[] args) {Scanner scan new Scanner(System.in);int n…...
RoboVQA:机器人多模态长范围推理
23 年 11 月来自 Google Deepmind 的论文“RoboVQA: Multimodal Long-Horizon Reasoning for Robotics”。 本文提出一种可扩展、自下而上且本质多样化的数据收集方案,该方案可用于长期和中期的高级推理,与传统的狭窄自上而下的逐步收集相比,…...
TCP/IP原理详细解析
前言 TCP/IP是一种面向连接,可靠的传输,传输数据大小无限制的。通常情况下,系统与系统之间的http连接需要三次握手和四次挥手,这个执行过程会产生等待时间。这方面在日常开发时需要注意一下。 TCP/IP 是互联网的核心协议族&…...
Microsof Visual Studio Code 安装教程(中文设置)
VS Code 是一个免费的代码编辑器,可在 macOS、Linux 和 Windows作系统上运行。启动和运行 VS Code 既快速又简单。VS Code(全称 Visual Studio Code)是一款由Microsoft 推出的免费、开源、跨平台的代码编辑器,拥有强大的功能和灵活…...
python爬虫:Android自动化工具Auto.js的详细使用
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. Auto.js 简介2. 安装与配置2.1 安装 Auto.js2.2 安装 Python 环境2.3 安装 ADB 工具3. Python 与 Auto.js 结合3.1 通过 ADB 执行 Auto.js 脚本3.2 通过 Python 控制 Auto.js3.3 通过 Python 与 Auto.js 交互4. 常用…...
Unity DOTS从入门到精通之 自定义Authoring类
文章目录 前言安装 DOTS 包什么是Authoring1. 实体组件2. Authoring类 前言 DOTS(面向数据的技术堆栈)是一套由 Unity 提供支持的技术,用于提供高性能游戏开发解决方案,特别适合需要处理大量数据的游戏,例如大型开放世…...
linux 软件安装(上)
一、基础环境准备 1.1、安装VM 1.2、在VM上导入linux iso镜像,装好linux系统 华为centos镜像下载地址 https://mirrors.huaweicloud.com/centos/ https://mirrors.huaweicloud.com/centos/7.9.2009/isos/x86_64/ 网易centos镜像下载地址 htt…...
php虚拟站点提示No input file specified时的问题及权限处理方法
访问站点,提示如下 No input file specified. 可能是文件权限有问题,也可能是“.user.ini”文件路径没有配置对,最简单的办法就是直接将它删除掉,还有就是将它设置正确 #配置成自己服务器上正确的路径 open_basedir/mnt/qiy/te…...
【江协科技STM32】ADC数模转换器-学习笔记
ADC简介 ADC(Analog-Digital Converter)模拟-数字转换器ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁,ADC是一种将连续的模拟信号转换为离散的数字信号的设备或模块12位逐次逼近型…...
QT系列教程(20) Qt 项目视图便捷类
视频连接 https://www.bilibili.com/video/BV1XY41127t3/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 Qt项目视图便捷类 Qt项目视图提供了一些便捷类,包括QListWidget, QTableWidget, QTreeWidget等。我们分别介绍这几个便捷类。 我们先创建一个Qt …...
git worktree的使用
git worktree 是 Git 提供的一个强大功能,允许你在同一个仓库中同时创建多个工作目录,每个目录对应一个分支,从而实现并行开发。以下是 git worktree 的常用命令和使用方法: 1. 创建新的工作目录(Worktree)…...
Spring Boot+RabbitMQ+Canal 解决数据一致性
目录大纲 一、环境配置1.1 docker-compose.yml 配置1.2 docker-compose 常用命令1.3 镜像服务启动状态 二、MySQL binlog 配置2.1 docker-compose command 配置 binlog2.2 创建canal用户,以及查看是否开启binlog 三、canal 相关配置文件3.1 canal.properties 完整文…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
OPENCV图形计算面积、弧长API讲解(1)
一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积,这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能,常用的API…...
Qt学习及使用_第1部分_认识Qt---Qt开发基本流程
前言 学以致用,通过QT框架的学习,一边实践,一边探索编程的方方面面. 参考书:<Qt 6 C开发指南>(以下称"本书") 标识说明:概念用粗体倾斜.重点内容用(加粗黑体)---重点内容(红字)---重点内容(加粗红字), 本书原话内容用深蓝色标识,比较重要的内容用加粗倾…...
