本文有以下几个目的:

  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/)便于技术栈管理,适合中小型项目。 两者无绝对优劣,需结合团队规模和业务复杂度选择, 但是无论如何每一个项目团队都应该做的,就是对业务进行建模分析,对团队开发形成整齐划一的技术规范。

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

领域驱动的事实与谬误 一 DDD 与 MVC的更多相关文章

  1. [转]DDD领域驱动设计基本理论知识总结

    领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...

  2. DDD领域驱动设计基本理论知识总结

    领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...

  3. 分享我对领域驱动设计(DDD)的学习成果

    本文内容提要: 1. 领域驱动设计之领域模型 2. 为什么建立一个领域模型是重要的 3. 领域通用语言(Ubiquitous Language) 4.将领域模型转换为代码实现的最佳实践 5. 领域建模 ...

  4. DDD领域驱动设计和实践(转载)

    -->目录导航 一. DDD领域驱动设计介绍 1. 什么是领域驱动设计(DDD) 2. 领域驱动设计的特点 3. 如果不使用DDD? 4. 领域驱动设计的分层架构和构成要素 5. 事务脚本和领域 ...

  5. DDD(Domain Driver Designer) 领域驱动设计简介

    领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...

  6. 我对领域驱动设计(DDD)的学习成果

    领域驱动设计之领域模型 2004年Eric Evans发表Domain-Driven Design – Tackling Complexity in the Heart of Software (领域 ...

  7. DDD领域驱动设计基本理论知识总结(转)

    领域驱动设计之领域模型 为什么建立一个领域模型是重要的 领域通用语言(UBIQUITOUS LANGUAGE) 将领域模型转换为代码实现的最佳实践 领域建模时思考问题的角度 领域驱动设计的经典分层架构 ...

  8. 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇

    前言 领域驱动设计,其实已经是一个很古老的概念了,但它的复杂度依旧让学习的人头疼不已. 互联网关于领域驱动的文章有很多,每一篇写的都很好,理解领域驱动设计的人都看的懂. 不过,这些文章对于那些初学者而 ...

  9. .net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇

    .net core +codefirst(.net core 基础入门,适合这方面的小白阅读)   前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以. ...

  10. 基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则

    目录 前言 聚合 聚合和聚合根原则 包含业务原则 单个单元原则 事务边界原则 可序列化原则 聚合和聚合根最佳实践 只通过ID引用其他聚合 用于 EF Core 和 关系型数据库 保持聚合根足够小 聚合 ...

随机推荐

  1. VScode中C/C++调试文件配置

    VScode中C/C++调试文件配置 //launch.json { "version": "2.0.0", "configurations" ...

  2. DeepSeek R1本地与线上满血版部署:超详细手把手指南

    一.DeepSeek R1本地部署 1.下载ollama下载地址 本人是Mac电脑,所以选第一项,下面都是以Mac环境介绍部署,下载好把ollama运行起来即可启动Ollama服务. Ollama默认 ...

  3. Typecho 博客文章评论添加显示 UserAgent(UA)的功能

    本篇文章实现了为 Typecho 博客文章评论添加显示 UserAgent(UA)的功能 本功能可替代 UserAgent 插件,更美观.简洁且好看 效果显示 大概就是这样了,实际效果请看我的评论! ...

  4. Python - qrcode(二维码模块)

    import qrcode codeText = 'https://www.cnblogs.com/houhuilinblogs' img = qrcode.make(codeText) print( ...

  5. 「一」vim简介

    什么是vim? 一个历史悠久的文本编辑器 vim采用了模式编辑的理念,提供了多种模式 底線命令模式 插入模式 命令模式 交互式教程 $: vimtutor :自带教程 $: vim -h : vim命 ...

  6. Vue3 路由配置与导航全攻略:从零到精通

    在现代前端开发中,单页应用(SPA)已经成为主流趋势.而作为 Vue.js 的核心功能之一,Vue Router 提供了强大的路由管理能力,帮助开发者轻松构建流畅.高效的单页应用.本文将带你深入探讨 ...

  7. MS17_010漏洞利用,渗透win7,拿到桌面的flag

    关于使用MS17_010来攻击WIN7: 我们先ping一下win7的ip看看是否可以ping通(ping不通的可以关闭win7的防火墙),然后我们用nmap扫一下看看靶机有什么漏洞 nmap --s ...

  8. Cordova基本使用(二)

    cordova的打包发布版app流程简介 除了第一遍官网给的打包发布版的方法,我们可以自己多敲几次命令来实现. 基本上使用如下的几个命令就完成这个过程,先列出整个过程: 1.cordova选定ando ...

  9. 『Plotly实战指南』--架构与设计理念

    在数据科学和数据分析领域,数据可视化是理解数据和传达信息的关键环节. Python 作为最受欢迎的编程语言之一,拥有众多强大的可视化库,而 Plotly 无疑是其中的佼佼者. 本文将深入介绍 Plot ...

  10. 深入解析 Druid 连接池:连接有效性检测与 Keep-Alive 机制

    背景 在 Java 程序中,下面是一个经常会碰到的错误. Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communica ...