领域驱动的事实与谬误 一 DDD 与 MVC

本文有以下几个目的:

  1. 让新手少交智商税,少浪费时间看一些软文。
  2. 普及一个基本概念:了解一项观点的提出年代和最初初衷,才能更好地掌握其精粹。
  3. 我想指出市场上一些误人子弟的软文。

首先说明:文中所说的谬误并非原书的谬误,而是很多网上水军写的软文在不断误人子弟、传播错误认知。

MVC到底在说什么

MVC(Model-View-Controller)架构由挪威计算机科学家Trygve Mikkjel Heyerdahl Reenskaug于1979年在施乐帕克研究中心(Xerox PARC)访问期间提出。这一架构最初是为Smalltalk编程语言设计的,旨在解决图形用户界面(GUI)开发中数据管理与用户交互的复杂性问题。当时Smalltalk的GUI需要支持动态交互(如用户操作实时更新数据),传统单体架构难以维护,MVC通过解耦输入-处理-输出流程,首次实现了界面与逻辑的分离。

Reenskaug认为,GUI应用需要将不同功能模块解耦,以应对数据复杂性和用户交互的动态性。他提出将软件系统划分为三个核心组件:

  • 模型(Model) :封装数据和业务逻辑,独立于界面展示,例如数据库结构或业务规则。
  • 视图(View):负责用户界面的呈现,直接与用户交互,例如窗口、按钮等可视化元素。
  • 控制器(Controller):协调模型与视图的交互,处理用户输入并更新模型状态,例如按钮点击后的逻辑判断。

关键澄清:MVC的Model本身包含基础业务逻辑(如数据验证),但复杂业务场景下需独立的应用逻辑层(如Service层)来组织流程,这与DDD的领域建模形成互补。因此,四层架构(Model-View-Controller-Service)的出现是企业级开发的演进,而非MVC原生缺陷。

DDD到底在说什么

DDD由Eric Evans 在2003年出版的经典著作《领域驱动设计:软件核心复杂性应对之道》中系统提出。其诞生源于对复杂业务系统开发困境的反思:

  1. 传统开发的痛点

    • 软件模型与真实业务领域脱节,导致需求频繁变更时难以维护;
    • 技术团队与领域专家(如业务分析师、行业专家)沟通低效,术语不统一,模型设计偏离实际业务逻辑;
    • 当业务复杂度高(如金融、供应链、医疗等领域)时,传统开发方法(如数据驱动设计、贫血模型)无法有效管理复杂性,代码逐渐沦为"意大利面条"。
  2. 核心目标

    Evans认为,应对复杂业务系统的关键在于将领域知识作为设计的核心,通过建立清晰、准确的领域模型,让技术实现紧密贴合业务本质,从而提升系统的可维护性和扩展性。

DDD分为两个层面:

  • 战略设计:通过限界上下文(Bounded Context)划分业务边界,明确领域模型的适用范围(如电商中的"订单域"与"支付域"),解决业务与技术对齐问题;
  • 战术设计:通过实体、值对象、聚合根等工具实现领域模型,确保业务规则封装在代码中。

DDD与MVC并不冲突

在传统MVC架构下,解决GUI问题时,我们会设计GUI层面的技术模型,再根据模型渲染界面。同理,解决业务逻辑问题时,也可以设计一个领域模型,再基于模型开发业务逻辑。

参考下图:

从图中不难看出:领域驱动设计的核心是教你如何设计业务逻辑------注意,是"业务逻辑设计",而非技术分层设计。原因很简单:DDD原书明确指出,这不是一本教你写代码的书,而是教你如何应对复杂软件的方法论。

通用原则 :无论哪个层面的技术开发,都可以先建模,再基于模型开发------这是几乎所有行业都在使用的通用手段。

DDD本来就不存在统一的代码规范,原书也未给出具体实现手段

回到上图,你会发现:任何一个技术维度的修改,都不需要其他维度的直接支持,甚至可以单独调整某个维度------这正是DDD在战术设计上想表达的理念。但这部分内容被放在原书的最后章节,不仅因为前面的章节是前提,更因为代码架构并非DDD的核心。

DDD的核心是什么?

  • 统一语言:团队(包括业务专家)使用一致的术语描述业务规则(如"订单已支付"对应领域事件);
  • 领域模型:围绕业务概念设计代码,而非围绕数据库或技术框架;
  • 解耦思想:通过聚合根、仓储等模式隔离业务逻辑与技术细节。

代码规范的真相

DDD不强制规定具体代码结构和命名,但业界基于实践形成了通用分层原则(如四层架构:表现层、应用层、领域层、基础设施层)。例如:

  • 领域层(Domain Layer)封装核心业务逻辑,包含实体、值对象、聚合根;
  • 应用层(Application Layer)协调领域对象,处理事务和权限;
  • 基础设施层(Infrastructure Layer)处理数据库、消息队列等技术细节。

争议与选择

业界关于代码结构的最大争议是按功能分包 vs 按技术层分包

  • 按功能分包(如order/ user/)利于业务模块隔离,适合大型复杂系统;
  • 按技术层分包(如controller/ service/)便于技术栈管理,适合中小型项目。 两者无绝对优劣,需结合团队规模和业务复杂度选择, 但是无论如何每一个项目团队都应该做的,就是对业务进行建模分析,对团队开发形成整齐划一的技术规范。

附录一些可以参考的代码和技术文章

相关推荐
九卷21 天前
微服务架构学习与思考(15):微服务拆分的原则、时机、方法以及常见问题
微服务·ddd·微服务架构·架构设计
lazy★boy1 个月前
DDD与MVC扩展能力对比
mvc·ddd
Jayden1 个月前
Spring Boot 实战:DDD 分层架构落地全解析
spring boot·ddd·ddd架构·ddd落地
lixww.cn3 个月前
ASP.NET Core用MediatR实现领域事件
ddd·asp.net core·mediatr
蜗牛沐雨3 个月前
在 Go 中实现事件溯源:构建高效且可扩展的系统
服务器·golang·ddd·事件驱动·领域驱动
小小工匠3 个月前
DDD - 整洁架构_解决技术设计困局
ddd·整洁架构
慧集通-让软件连接更简单!4 个月前
慧集通(DataLinkX)iPaaS集成平台-业务建模之业务对象(四)
数据库·ui·api·ddd·系统集成·业务对象·业务建模
慧集通-让软件连接更简单!4 个月前
慧集通(DataLinkX)iPaaS集成平台-业务建模之业务对象(一)
数据库·api·ddd·系统集成·集成平台·业务对象·业务建模
rolt4 个月前
[pdf、epub]260道《软件方法》强化自测题业务建模需求分析共216页(202412更新)
ddd·需求分析·架构师·uml·领域驱动设计