《实现领域驱动设计》

news2024/12/15 21:38:09

DDD入门

1.1 DDD是什么?

DDD是一种软件开发方法

  • DDD将领域专家和开发人员聚集到一起,开发的软件能够反映出领域专家的思维模型。目标是:交付最具业务价值的软件。
  • DDD关注业务战略:指引我们如何实现面向服务架构(service-oriented architecture)或者业务驱动(business-driven architecture)架构。
  • 使用战术设计建模工具:这些战术设计工具使开发人员能够按照领域专家的思维模型开发软件。保证成功地交付真正的业务价值。

1.2 为什么我们需要DDD?

  • 使领域专家和开发者在一起工作,这样开发的软件能够准确地传达业务规则。
  • "准确传达业务规则"意思是说:此时的软件就像是领域专家是编码人员时所开发出来的一样。
  • 可以帮助业务人员自我提高。在DDD中,每个人都在学习,同时每个人又是知识的贡献者。
  • 关键在于对于知识的集中,确保软件知识并不只是掌握在少数人手中。
  • 在领域专家、开发者和软件本身之间不存在"翻译"
  • 设计就是代码,代码就是设计
  • DDD提供了战略设计和战术设计两种方式。
    战略设计:帮助我们理解哪些投入是最重要的;
    战术设计:帮助我们创建DDD模型中各个部件。

1.3 如何DDD?

通用语言、限界上下文(Bounded Context)同时构成了DDD的两大支柱,并且它们是相辅相成的。

通用语言
通用语言是团队共享的语言。领域专家和开发者使用相同的通用语言进行交流。事实上,团队中每个人都使用相同的通用语言。不管你再团队中的角色如何,只要你是团队的一员,都将使用通用语言。团队成员通过讨论、参考资料、引用标准、查阅字典等对通用语言进行改进。有时我们发现,有些我们曾经认为能很好表达业务的词汇不再适用了,而另外的一些词汇具有更好的效果。

1.4 使用DDD的业务价值

不管使用什么技术,我们的目的都是提供业务价值。

我们可以将DDD的业务价值大致总结为以下几点:

1.你获得了一个非常有用的领域模型
2.你的业务得到了更准确的定义和理解
3.领域专家可以为软件设计做出贡献
4.更好的用户体验
5.清晰的模型边界
6.更好的企业架构
7.敏捷、选代式和持续建模
8.使用战略和战术新工具

1.5 实施DDD所面临的挑战

  • 为创建通用语言腾出时间和精力
    使用DDD最大的挑战之一便是:我们需要花费大量的时间和精力来思考业务领域,研究概念和术语,并且和领域专家交流,以发现、捕捉和改进通用语言。如果你想完全采用DDD来最大化业务价值,你需要做出很多努力,并且花费很多时间。
  • 持续地将领域专家引入项目
    要将领域专家引入你的项目恐怕也不是一件易事。但是不管有多么困难,这是你必须做的。如果你连一个领域专家都找不到,那么你根本无法对一个领域有深入的理解。
  • 改变开发者对领域的思考方式
    多数开发者在采用DDD时都需要转变自己思考问题的方式。作为开发者,我们都是技术思想者,技术实现对于我们来说并不是什么难事。我并不是说技术地思考不好,只是说有时少从技术层面去思考会更好。这么多年来,我们都习惯了单从技术层面完成软件开发,那么现在,是时候考虑一种新的思考方式了。为你的业务领域开发一门通用语言便是一个好的出发点。

2 领域、子域、界限上下文

由于“领域模型”包含了“领域”这个词,我们可能会认为应该为整个业务系统创建一个单一的、内聚的、全功能式的模型。然而,这并不是我们使用DDD的目标。正好相反,在DDD中,一个领域被分为若干子域,领域模型在限界上下文中完成开发。事实上,在开发一个领域模型时,我们关注的通常只是这个业务系统的某个方面。
工作中的子域和限界上下文
在这里插入图片描述

将关注点放在核心域上
在这里插入图片描述
图2.2上半部分的领域边界,你会看到一个叫核心域的子域。
对于核心域,它是整个业务领域的一部分,也是业务成功的主要促成因素。从战略层面上讲,企业应该在核心域上胜人一筹。我们应该给予核心域最高的优先级、最资深的领域专家和最优秀的开发团队。在实施DDD的过程中,你将主要关注于核心域。

图2.2中还展示了另外两种子域:支撑子域和通用子域
有时,我们会创建或者购买某个限界上下文来支撑我们的业务。如果这样的限界上下文对应着业务的某些重要方面,但却不是核心,那么它便是一个支撑子域
创建支撑子域的原因在于它们专注于业务的某个方面,否则,如果一个子域被用于整个业务系统,那么这个子域便是通用子域
我们并不能说支撑子域和通用子域是不重要的,它们是重要的,只是我们对它们的要求并不像核心域那么高。

2.1 战略设计为什么重要

2.2 现实世界中领域和子域

领域中还同时存在问题空间(problem space)和解决方案空间(solution space)在问题空间中,我们思考的是业务所面临的挑战,而在解决方案空间中,我们思考如何实现软件以解决这些业务挑战。
以下是如何将这两者应用到我们已经学过的知识中:

  • 问题空间是领域的一部分,对问题空间的开发将产生一个新的核心域。
    对问题空间的评估应该同时考虑已有子域和额外所需子域。因此,问题空间是核心域和其他子域的组合。问题空间中的子域通常随着项目的不同而不同,他们各自关注于当前的业务问题,这使得子域对于问题空间的评估非常有用。子域允许我们快速地浏览领域中的各个方面,这些方面对于解决特定的问题是必要的。
  • 解决方案空间包括一个或多个限界上下文,即一组特定的软件模型。
    这是因为限界上下文即是一个特定的解决方案,它通过软件的方式来实现解决方案。

2.3 理解限界上下文

在很多情况下在不同模型中存在名字相同或相近的对象,但是它们的意思却不同。当模型被一个显式的边界所包围时,其中每个概念的含义便是确定的了。因此,限界上下文主要是一个语义上的边界,我们应该通过这一点来衡量对一个限界上下文的使用正确与否。

在这里插入图片描述

不同限界上下文中的Account对象具有完全不同的含义
银行上下文:账户表示一个客户在银行的存款支票账户和储蓄账户
状态,并记录每次交易信息。
文学上下文:账户表示用文字记录的在一段时间之内发生的一系列事件。

在通常情况下,我们所面对的都是一些区别甚小的概念定义。原因在于:在一个上下文中,团队通常根据通用语言来命名某个概念。我们并不会随意地命名一个概念以刻意地保持与其他上下文的不同。

比如两个银行上下文,一个用于支票账户另一个用于储蓄账户。在支票上下文(Checking
Context)中我们不必使用支票账户(CheckingAccount);在储蓄上下文(Saving Context)中我们也不必使用储蓄账户(SavingAccount)。两个概念都可以使用账户(Account)来表示因为限界上下文已经对此做了区分。当然,我们并没有规定不能使用更具体的名字这只是团队自己的选择而已。

当需要集成时,我们必须在不同的限界上下文之间进行概念映射。
限界上下文不仅仅只包含模型
一个限界上下文并不是只包含领域模型。诚然,模型是限界上下文的主要“公民”。但是,限界上下文并不只局限于容纳模型,它通常标定了一个系统、一个应用程序或者一种业务服务”。有时,限界上下文所包含的内容可能比较少,比如,一个通用子域便可以只包含领域模型。

限界上下文主要用来封装通用语言和领域对象,但同时它也包含了那些为领域模型提供交互手段和辅助功能的内容。需要注意的是,对于架构中的每个组件,我们都应该将其放在适当的地方。
限界上下文的大小
限界上下文应该足够大,以能够表达它所对应的整套通用语言。

核心领域之外的概念不应该包含在限界上下文中。如果一个概念不属于你的通用语言,那么一开始你就不应该将其引入到模型中。

与技术组件保持一致
将限界上下文想成是技术组件并无大碍,只是我们需要记住:技术组件并不能定义限界上下文。
在这里插入图片描述
让我们来看看示例DDD项目中的这3个限界上下文。他们分别是协作上下文身份与访问上下文敏捷项目管理上下文

协作上下文
在这里插入图片描述
协作上下文的团队将所有与安全和权限相关的模块和类型从该上下文中移除,然后逐渐采用新的身份与访问上下文。

身份与访问上下文

现在,多数企业级应用程序都需要某种形式的安全和权限组件,这样的组件用以对用户进行认证和授权。正如我们在前面所分析的,一种幼稚的做法是将这样的组件嵌入到每一个离散的系统中,这将导致每一个系统都产生筒仓效应(siloeffect) .
在这里插入图片描述
当有我们关心的状态由于模型行为而发生改变时,系统将发布领域事件(8)。

敏捷项目管理上下文
在这里插入图片描述

3 上下文映射图

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

3.1 上下文映射图为什么重要

在这里插入图片描述
你的映射图可以使你了解到映射图的内部,并且可以指明在哪些地方需要与其他团队进行交流。尽早绘制上下文映射图,这样可以迫使你仔细思考你的项目和你所依赖项目之间的关系。

绘制上下文映射图
上下文映射图并不是一种企业架构,也不是系统拓扑图。但是,它可以用于高层次的架构分析,指出诸如集成瓶颈之类的架构不足。上下文映射图展现了一种组织动态能力(organizational dynamic)它可以帮助我们识别出有碍项目进展的一些管理问题。
限界上下文之间的关系

  • 合作关系(Partnership)
  • 共享内核(SharedKernel)
    对模型和代码的共享将产生一种紧密的依赖性。
    对于设计来说,这种依赖性可好可坏。我们需要为共享的部分模型指定一个显式的边界,并保持共享内核的小型化。
  • 客户方-供应方开发(Customer-Supplier Development)
    当两个团队处于一种上游-下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能会受到很大的影响。
  • 遵奉者(Conformist)
    在存在上游-下游关系的两个团队中如果上游团队已经没有动力提供下游团队之所需,下游团队便孤军无助了。
  • 防腐层(Anticorruption Layer)
    防腐层通过已有的接口与其他系统交互,而其他系统只需要做很小的修改,甚至无须修改。在防腐层内部,它在你自己的模型和他方模型之间进行翻译转换。
  • 开放主机服务(Open Host Service)
    定义一种协议,让你的子系统通过该协议来访问你的服务。
  • 发布语言(Published Language)
    在两个限界上下文之间翻译模型需要一种公用的语言。
  • 另谋他路(SeparateWay)
    在确定需求时我们应该做到坚决彻底。如果两套功能没有显著的关系,那么它们是可以被完全解耦的。
  • 大泥球(Big Ballof Mud)
    当我们检查已有系统时经常会发现系统中存在混杂在一起的模型,它们之间的边界是非常模糊的。此时你应该为整个系统绘制一个边界,然后将其归纳在大泥球范围之列。
映射3个示例限界上下文

在这里插入图片描述
身份与访问上下文位于最上游它对协作上下文和敏捷项目管理上下文均会产生影响。同时,协作上下文又是敏捷项目管理上下文的上游,因为后者的模型依赖于前者的模型和服务。

所有下游系统的连接框都标以ACL,即防腐层。对于它们的技术实现将在集成限界上下文(13)中讲到。

协作上下文
协作上下文通过传统的类似于RPC的方式获取外部资源。协作上下文并不会永久性地记录下从身份与访问上下文中获取来的数据而是在每次需要数据时重新向远程系统发出请求。
在这里插入图片描述
敏捷项目管理上下文
为了达到比RPC更高的自治性,敏捷项目管理上下文的团队将尽量限制对RPC的使用,此时他们可以选择异步请求,或者事件处理等方式。

DDD的做法是:在本地创建一些由外部模型翻译而成的领域对象,这些对象保留着本地模型所需的最小状态集。为了初始化这些对象,我们只需要有限的RPC调用或REST请求。然而,要与远程模型保持同步,最好的方式是在远程系统中采用面向消息的通知(notification)机制。消息通知可以通过服务总线进行发布也可以采用消息队列或者REST。
在这里插入图片描述

和身份与访问上下文集成
在这里插入图片描述
敏捷项目管理上下文在本地有DiscussionService和SchedulingService,它们是领域服务,用于管理协作系统中的讨论和日历条目

4 架构

DDD的一大好处便是它并不需要使用特定的架构。由于核心域(2)位于限界上下文(2)中我们可以在整个系统中使用多种风格的架构有些架构包围着领域模型,能够全局性地影响系统,而有些架构则满足了某些特定的需求。我们的目标是选择适合于自己的架构和架构模式。

4.2 分层

分层架构模式[Buschmannetal被认为是所有架构的始祖它支持N层架构系统,因此被广泛地应用于Web、企业级应用和桌面应用。在这种架构中,我们将一个应用程序或者系统分为不同的层次。
图4.1所示为一个典型的DDD系统所采用的传统分层架构,其中核心域只位于架构中的其中一层其上为用户界面层(User Interface)和应用层(ApplicationLayer),其下是基础设施层(Infrastructure Layer)。

在这里插入图片描述

4.3 六边形架构 (端口与适配器)

4.4 面向服务架构SOA

4.5 REST

4.6 命令和查询职责分离

CORS

4.7 事件驱动架构

4.8 数据网织和基于网格的分布式计算

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1140884.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开题报告怎么写?-案例+模板保姆级)

以前导师让们带本科生开题报告,我深知开题报告在学术研究中的重要性。一个出色的开题报告能够展示学生的科学思维、研究能力和创新潜力。 在本篇博客中,我将为大家详细介绍如何撰写史上最强开题报告。 将从课题的 科学意义国内外研究概况和发展趋势应…

SourceTree 使用

如何拉取远程仓库?如何拉去远程分支?如何创建本地分支?如何删除本地分支?如何删除远端分支? 删除了远程分支,如果本地还有此分支,那么是可以通过推送本地分支来还原远端分支。如何合并本地分支&…

2023中国计算机大会:蚂蚁集团连发两支百万级科研基金

10月26日,中国计算机学会(CCF)主办的第二十届中国计算机大会(CNCC2023)在沈阳举行。在“CCF-蚂蚁科研基金及产学研合作交流活动”上,蚂蚁集团发布了2023年度“CCF-蚂蚁科研基金”绿色计算及隐私计算两支百万级专项基金&#xff0c…

动态代理IP怎么设置?动态代理IP有哪些应用场景?

动态代理IP是指代理服务器会根据实际IP地址的变化而变化,可以帮助用户隐藏真实的IP地址,同时可以在不同的网络环境下使用不同的代理IP地址。下面是动态代理IP的设置和应用场景: 一、动态代理IP怎么设置? 1. 手动设置代理IP地址 用…

基于Arduino的物流分拣控制系统设计

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、控制系统设计1.1系统方案1.2 系统工作原理1.3方案设计1.3.1快递检测电路方案设计1.3.2控制电路方案设计 二、硬件…

【Java基础】File类与IO流

File类与IO流 文章目录 File类与IO流1. java.io.File类的使用1.1 概述1.2 构造器1.3 作用 2. IO流原理及流的分类2.1 流的分类2.3 流的API 3. 节点流之一:FileReader\FileWriter3.1 Reader与Writer3.3 关于flush(刷新) 4. 节点流之二&#xf…

GPIO常见名词——推挽、开漏、浮空、上拉、下拉、高阻态

🙌秋名山码民的主页 😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 获取源码,添加WX 目录 1、前言…

VTK OrientationMarker 方向 三维坐标系 相机坐标轴 自定义坐标轴

本文 以 Python 语言开发 我们在做三维软件开发时,经常会用到相机坐标轴,来指示当前空间位置; 坐标轴效果: 相机方向坐标轴 Cube 正方体坐标轴 自定义坐标轴: Code: Axes def main():colors vtkNamedC…

以太网通讯与485通讯哪个好?

随着工业自动化、物联网和信息技术的快速发展,数据传输成为了各个领域越来越关注的问题。在众多通讯技术中,以太网通讯和485通讯被广泛应用于各种场景。那么,这两种通讯技术究竟哪个更好呢?接下来,小编就来为大家一一讲…

使用Terraform管理已经存在的kubernates和默认的节点池

背景: 通过terraform resource "alicloud_cs_managed_kubernetes" "k8s" {...}创建集群时,会产生一个默认的节点池default-nodepool,但是如何去修改这个默认节点池的信息呢? 解决思路: 因为Ter…

LLM系列-大模型技术汇总

LLM系列-大模型技术汇总 1. 大模型技术汇总-参数高效迁移学习方法2. 千亿模型并行训练技术2.1. 数据并行(Data Parallelism,DP)2.2. 模型并行(Model Parallelism,MP)2.2.1. 流水线并行(Pipeline…

Ubuntu16.04 python matplotlib 输出轴标签出现中文乱码

问题:坐标轴打印中文时,显示会乱码 import matplotlib.pyplot as plt plt.ylabel(时间刻度)原因:matplotlib里面没有中文字体解决方法:下载SimHei字体,快捷方法是使用everything直接在windows搜索simhei.ttf&#xff…

【0230】PG内核底层事务(transaction)实现原理之基础篇

1. 事务上层 事务是如何工作? 接下来让我们通过gdb方式来跟踪一下PG内核中事务的底层工作原理。 (1)psql登录PG服务(2)psql登录界面输入:begin(3)gdb跟踪backend进程读取用户的输入,并进入exec_simple_query()函数函数exec_simple_query()的实现如下: static void …

JAVA实现学生日常行为评分管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.2.1 登录注册模块2.2.2 用户管理模块2.2.3 评分项目模块2.2.4 评分数据模块2.2.5 数据字典模块 2.3 可行性设计2.4 用例设计2.5 数据库设计2.5.1 整体 E-R 图2.5.2 用户2.5.3 评分项目2.5.4 评分数据2.5.…

PyTorch入门教学——torchvision中数据集的使用

1、torchvision.datasets datasets是torchvision工具集中的一个工具。可以理解为调用官方数据集的一种方式,其中有很多开源的数据集,可供我们学习使用。datasets官网:Datasets — Torchvision 0.16 documentation (pytorch.org) 2、使用 …

【漏洞复现】用友OA用户信息泄露

漏洞描述 通过该接口可下载oa用户信息文件 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技…

链游风暴再起?MBOX即将再度起飞

近期链游再次进入了我们的视野,Play To Earn在21年大放异彩之后经过了2年沉寂近期终于有了再度爆发的征兆,不管是前段时间爆拉7倍的YGG,还是近期一路高歌猛进的MC都已经吹响了链游板块即将冲锋的信号,那么近期还有哪些值得关注的链…

element form中input使用@keyup.enter.native回车页面刷新问题

当form中只有一个文本框的时候,使用keyup.enter.native会自动触发form的submit提交事件 地址栏会多出来一个? 解决方案: 在form中添加 submit.native.prevent ,阻止form提交默认事件

什么c++流行造轮子而不是调包侠?

什么c流行造轮子而不是调包侠? 因为在c(和c)中,你造的轮子是真的可以跟官方的轮子拼性能的,只要你的算法足够优秀,实现足够小心。 最近很多小伙伴找我,说想要一些c资料,然后我根据自…

大语言模型(LLM)综述(四):如何适应预训练后的大语言模型

A Survey of Large Language Models 前言5. ADAPTATION OF LLMS5.1 指导调优5.1.1 格式化实例构建5.1.2 指导调优策略5.1.3 指导调优的效果5.1.4 指导调优的实证分析 5.2 对齐调优5.2.1 Alignment的背景和标准5.2.2 收集人类反馈5.2.3 根据人类反馈进行强化学习5.2.4 无需 RLHF…