首页 系统架构 领域驱动的事实与谬误 一 DDD 与 MVC

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

本文有以下几个目的:

让新手少交智商税,少浪费时间看一些软文。
普及一个基本概念:了解一项观点的提出年代和最初初衷,才能更好地掌握其精粹。
我想指出市场上一些误人子弟的软文。
首先说明:文中所说的谬误并非原书的谬误,而是很多网上水军写的软文在不断误人子弟、传播错误认知。

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年出版的经典著作《领域驱动设计:软件核心复杂性应对之道》中系统提出。其诞生源于对复杂业务系统开发困境的反思:

传统开发的痛点:

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

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

战略设计:通过限界上下文(Bounded Context)划分业务边界,明确领域模型的适用范围(如电商中的"订单域"与"支付域"),解决业务与技术对齐问题;
战术设计:通过实体、值对象、聚合根等工具实现领域模型,确保业务规则封装在代码中。
DDD与MVC并不冲突
  在传统MVC架构下,解决GUI问题时,我们会设计GUI层面的技术模型,再根据模型渲染界面。同理,解决业务逻辑问题时,也可以设计一个领域模型,再基于模型开发业务逻辑。

 

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

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

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

DDD的核心是什么?

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

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

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

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

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

站星网

本文有以下几个目的:让新手少交智商税,少浪费时间看一些软文。普及一个基本概念:了解一项观点的提出年代..

为您推荐

大数据领域面临的挑战与未来的演进趋势

序有群友提了一个关于大数据行业当前发展状况的问题。暂时先用GPT帮我们对此问题,搜罗和总结一二。其一,此问题较为宏大,需要结合个人实践、对行业的综合认知做深度思考,较为耗时。短时间内,懒于再一一总结和思..

领域驱动设计,让程序员心中有码(七)

-设计原则和设计模式,互联网开发者们共同的追求 前言多年来,笔者一直从事传统软件企业的软件开发和项目管理工作。笔者发现在众多的传统软件企业中,评判优秀开发者的标准往往是技能的熟练程度,基本上都是以梭代码..

一文搞懂SaaS架构建设流程:业务战略设计、架构蓝图设计、领域系统架构设计、架构治理与实施

大家好,我是汤师爷~SaaS架构建设是一项复杂的系统工程,不仅需要技术层面的实现,更要从业务战略、架构设计、治理与实施等多个维度进行全面规划。一个成功的SaaS架构可以帮助企业降低IT成本、提升业务灵活性、加快..

领域驱动设计,让程序员心中有码(六)

领域驱动设计-聚合,一种极简的思维模式引言 作为IT技术产业飞速发展的产物,软件工程学已经成为当今时代非常重要的一个学科。作为一名资深的软件开发从业者,我们需要学习的东西实际上已经远远超出了原本在大学教育..

《实现领域驱动设计》笔记——上下文映射图

一个项目的上下文映射图可以用方式来表示。比较容易的一种是画一个简单的框图表示两个或多个限界上下文之间的映射关系。该框图表示了不同的限界上下文在解决方案空间中是如何通过集成相互关联的。另一种更详细的方式..

.NET 高级程序员面试题和答案

在.NET高级程序员的面试中,通常会涉及到一系列深入的技术问题,这些问题旨在评估候选人的编程能力、系统设计理解以及对.NET平台和相关技术的掌握程度。以下是一些可能的面试问题及其简要答案:如何在Controller中注..

发表回复

返回顶部

微信分享

微信分享二维码

扫描二维码分享到微信或朋友圈

链接已复制