在DDD中应用模式

深层模型和柔性设计并非唾手可得。要想取得进展,必须学习大量领域知识并进行充分的讨论,还需要经历大量的尝试和失败。但有时我们也能从中获得一些优势。一位经验丰富的开发人员在研究领域问题时,如果发现了他所熟悉的某种职责或某个关系网,他会想起以前这个问题是如何解决的。以前尝试过哪些模型?哪些是有效的?在实现中有哪些难题?它们是如何解决的?先前经历过的尝试和失败会突然间与新的情况联系起来。这些模式当中有一些已经记载到文献中供大家分享,这样我们就可以借鉴这些积累的经验。
利用分析模式和设计模式,可以避免一些代价高昂的尝试和失败过程,而直接从一个已经具有良好表达力和易实现的模型开始工作,并解决了一些可能难于学习的微妙的问题。我们可以从这样一个起点来重构和试验。然而,它们并不是现成的解决方案。

应用分析模式

在《分析模式》一书中,Martin Fowler这样定义分析模式[Fowler 1997, p. 8]:分析模式是一种表示业务建模中的常见构造的概念集合,用来表示业务建模中的常见结构。它可能只与一个领域有关,也可能跨越多个领域。
Fowler所提出的分析模式来自于实践经验,因此只要用在合适的情形下,它们会非常实用。对于那些面对着具有挑战性领域的人们,这些模式为他们的迭代开发过程提供了一个非常有价值的起点。"分析模式"这个名字本身就强调了其概念本质。分析模式并不是技术解决方案,他们只是些参考,用来指导人们设计特定领域中的模型。
但从这个名字中我们看不出分析模式也讨论了大量实现问题,包括一些代码。Fowler知道,在不考虑实际设计的情况下进行单纯的分析是有缺陷的。下面举一个很有趣的例子,在这个例子中,Fowler用更长远的眼光审视了模型选择的意义——考虑在部署之后,模型选择对系统长期维护的影响[Fowler 1997, p. 151]。
在一个成熟的项目上,模型选择往往是根据实用经验做出的。人们已经尝试了各种组件的多种实现方法。其中的一些实现已经被采用,有些甚至已经到了维护阶段。这些经验可以帮助人们避免很多问题。**分析模式的最大作用是借鉴其他项目的经验,把那些项目中有关设计方向和实现结果的广泛讨论与当前模型的理解结合起来。**脱离具体的上下文来讨论模型思想不但难以落地,而且还会造成分析与设计严重脱节的风险,而这一点正是MODEL-DRIVEN DESIGN坚决反对的。用实际的例子比用单纯的抽象描述能够更好地解释分析模式的原则和应用。
本章的目的不是对分析模式进行归纳分类,本章的重点是说明如何将它们集成到领域驱动的设计过程中。

分析模式的价值

当你可以幸运地使用一种分析模式时,它一般并不会直接满足你的需求。但它为你的研究提供了有价值的线索,而且提供了明确抽象的词汇。它还可以指导我们的实现,从而省去很多麻烦。
我们应该把所有分析模式的知识融入到知识消化和重构的过程中,从而形成更深刻的理解,并促进开发。当我们应用一种分析模式时,所得到的结果通常与该模式的文献中记载的形式非常相像,只是因具体情况不同而略有差异。但有时完全看不出这个结果与分析模式本身有关,然而这个结果仍然是受该模式思想的启发而得到的。
但有一个误区是应该避免的。当使用众所周知的分析模式中的术语时,一定要注意,不管其表面形式的变化有多大,都不要改变它所表示的基本概念。这样做有两个原因,一是模式中蕴含的基本概念将帮助我们避免问题,二是(也是更重要的原因)使用被广泛理解或至少是被明确解释的术语可以增强UBIQUITOUS LANGUAGE。如果在模型的自然演变过程中模型的定义也发生改变,那么就要修改模型名称了。
很多对象模型都有文献资料可查,其中有些对象模型专门用于某个行业中的某种应用,而有些则是通用模型。大部分对象模型都有助于开阔思路,但只有为数不多的一些模型精辟地阐述了选择这些模式的原理和使用的结果,而这些才是分析模式的精华所在。这些精化后的分析模式大部分都很有价值,有了它们,可以免去一次次的重复开发工作。尽管我们不大可能归纳出一个包罗万象的分析模式类目,但针对具体行业的类目还是能够开发出来的。而且在一些跨越多个应用的领域中适用的模式可以被广泛共享。
这种对已组织好的知识的重复利用完全不同于通过框架或组件进行的代码重用,但是二者唯一的共同点是它们都提供了一种新思路的萌芽,而这种新思路先前可能并不十分明晰。一个模型,甚至一个通用框架,都是一个完整的整体,而分析则相当于一个工具包,它被应用于模型的一些部分。分析模式专注于一些最关键和最艰难的决策,并阐明了各种替代和选择方案。它们提前预测了一些后期结果,而如果单靠我们自己去发现这些结果,可能会付出高昂的代价。

将设计模式应用于模型

设计模式(design pattern)——设计模式是对一些互相交互的对象和类的描述,我们通过定制这些对象和类来解决特定上下文中的一般设计问题[Gamma et al. 1995, p. 3]。
到目前为止,本书所探讨的模式都是专门用来在MODEL-DRIVEN DESIGN的上下文中解决领域模型的问题。但实际上,大部分已发布的模式都更侧重于解决技术问题。设计模式与领域模式之间有什么区别?《设计模式》这部经典著作的作者为初学者指出了以下事实[Gamma et al. 1995, p. 3]:
立场不同会影响人们如何看待什么是模式以及什么不是模式。一个人所认为的模式在另一个人看来可能是基本构造块。本书将在一定的抽象层次上讨论模式。设计模式并不是指像链表和散列表那样可以被封装到类中并供人们直接重用的设计,也不是用于整个应用程序或子系统的复杂的、领域特定的设计。本书中的设计模式是对一些交互的对象和类的描述,我们通过定制这些对象和类来解决特定上下文中的一般设计问题。
在《设计模式》中,有些(但并非所有)模式可用作领域模式,但在这样使用的时候,需要变换一下重点。《设计模式》中的设计模式把相关设计元素归为一类,这些元素能够解决在各种上下文中经常遇到的问题。这些模式的动机以及模式本身都是从纯技术角度描述的。但这些元素中的一部分在更广泛的领域和设计上下文中也适用,因为这些元素所对应的基本概念在很多领域中都会出现。
除了《设计模式》中介绍的模式以外,近年来还出现了其他很多技术设计模式。有些模式反映了在一些领域中出现的深层概念。这些模式都有很大的利用价值。为了在领域驱动设计中充分利用这些模式,我们必须同时从两个角度看待它们:从代码的角度来看它们是技术设计模式,从模型的角度来看它们就是概念模式
我们将把《设计模式》所介绍的特定模式作为样例,来说明如何将人们所认为的设计模式应用到领域模型中,而且这个例子还将澄清技术设计模式与领域模式之间的区别。本章还将通过COMPOSITE(组合)和STRATEGY(策略)这两种模式演示如何通过改变思考方式,用一些经典的设计模式来解决领域问题。

模式:STRATEGY(也称为POLICY)

请添加图片描述

领域模型包含一些并非用于解决技术问题的过程,将它们包含进来是因为它们对处理问题领域具有实际的价值。当必须从多个过程中进行选择时,选择的复杂性再加上多个过程本身的复杂性会使局面失去控制。
当对过程进行建模时,我们经常会发现过程有不止一种合理的实现方式,而如果把所有的可选项都写到过程的定义中,定义就会变得臃肿而复杂,而且可供我们选择的实际行为也会因为混杂在其他行为中而显得模糊不清。
我们希望把这些选择从过程的主体概念中分离出来,这样既能够看清主体概念,也能更清楚地看到这些选择。软件设计社区中众所周知的STRATEGY模式就是为了解决这个问题的,虽然它的侧重点在于技术方面。这里,我们把它当成模型中的一个概念来使用,并在该模型的代码实现中把它反映出来。我们同样也需要把过程中极易发生变化的部分与那些更稳定的部分分离开。
我们需要把过程中的易变部分提取到模型的一个单独的"策略"对象中。将规则与它所控制的行为区分开。按照STRATEGY设计模式来实现规则或可替换的过程。策略对象的多个版本表示了完成过程的不同方式。
通常,作为设计模式的STRATEGY侧重于替换不同算法的能力,而当其作为领域模式时,其侧重点则是表示概念的能力,这里的概念通常是指过程或策略规则。
我们在领域层中使用技术设计模式时,必须认识到这样做的另外一种动机,也是它的另一层含义。当所使用的STRATEGY对应于某种实际的业务策略时,模式就不再仅仅是一种有用的实现技术了(但它在实现方面的价值并未改变)。
设计模式的结论也完全适用于领域层。例如,在《设计模式》一书中,Gamma等人指出客户必须知道不同的STRATEGY,这也是建模的一个关注点。如果单纯从实现上来考虑,使用策略可能会增加系统中对象的数目。如果这是个问题,可以把STRATEGY实现为无状态对象,以便在上下文中进行共享,从而减小开销。《设计模式》中对实现方法的全面讨论在这里也适用,这是因为我们仍然在使用STRATEGY,只是动机稍有不同,这会对我们的选择产生一些影响,但设计模式中的经验仍然是可以借鉴的。

模式:COMPOSITE

请添加图片描述

在对复杂的领域进行建模时,我们经常会遇到由多个部分组成的重要对象,这些部分本身又由其他一些部分组成,依此类推,有时甚至会出现任意深度的嵌套。在一些领域中,各层嵌套在概念上是有区别的,但在另一些领域中,各个部分与它们所组成的整体是完全相同的事物,只是规模较小一些而已。
当嵌套容器的关联性在模型中没有反映出来时,公共行为必然会在层次结构的每一层重复出现,而且嵌套也变得僵化(例如,容器通常不能包含同一层中的其他容器,而且嵌套的层数也是固定的)。客户必须通过不同的接口来处理层次结构中的不同层,尽管这些层在概念上可能没有区别。通过层次结构来递归地收集信息也变得非常复杂。
**当在领域中应用任何一种设计模式时,首先关注的问题应该是模式的意图是否确实适合领域概念。**以递归的方式遍历一些相互关联对象确实比较方便,但它们是否真的存在整体—部分层次结构?你是否发现可以通过某种抽象方式把所有部分都归到同一概念类型中?如果你确实发现了这种抽象方式,那么使用COMPOSITE可以令模型的这些部分变得更清晰,同时使你能够借助设计模式所提供的那些经过深思熟虑的设计及实现的考量。
定义一个把COMPOSITE的所有成员都包含在内的抽象类型。在容器上实现那些查询信息的方法时,这些方法返回由容器内容所汇总的信息。而"叶"节点则基于它们自己的值来实现这些方法。客户只需使用抽象类型,而无需区分"叶"和容器。
相对而言,这是一种明显的结构层面上的模式,但设计人员通常不会主动地充实它的操作方面。COMPOSITE模式在每个结构层上都提供了相同的行为,而且无论是较小的部分还是较大的部分,都可以对这些部分提出一些有意义的问题,这些问题能够透明地反映出它们的构成情况。这种严格的对称是组合模式具有强大能力的关键所在。
设计模式应该仅仅在需要的时候才使用。

为什么没有介绍FLYWEIGHT

FLYWEIGHT虽然是设计模式的一个典型的例子,却并不适用于领域模型。
当一个VALUE OBJECT集合(其中的值对象数目有限)被多次使用的时候(如房屋规划中电源插座的例子),那么把它们实现为FLYWEIGHT可能是有意义的。这是一个适用于VALUE OBJECT(但不适用于ENTITY)的实现选择。COMPOSITE模式与它的不同之处在于,组合模式的概念对象是由其他概念对象组成的。这使得组合模式既适用于模型,也适用于实现,这是领域模式的一个基本特征。
本文并不打算把那些可以当作领域模式使用的设计模式完整地列出来。虽然没有一个把"解释器"(interpreter)用作领域模式的例子,但也不能断言解释器不适用于任何一种领域概念。把设计模式用作领域模式的唯一要求是这些模式能够描述关于概念领域的一些事情,而不仅仅是作为解决技术问题的技术解决方案。

参考

《领域驱动设计 软件核心复杂性应对之道》 Eric Evans 著, 赵俐 盛海艳 刘霞 等译, 任发科 审校

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

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

相关文章

[数据集][目标检测]电力场景输电线杆塔塔架金属锈蚀腐蚀生锈检测数据集VOC+YOLO格式1344张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):1344 标注数量(xml文件个数):1344 标注数量(txt文件个数):1344 标注…

makefile编译

文章目录 一、g和gcc的区别二、Linux下静态库和动态库三、makefile文件如何去编写 一、g和gcc的区别 基本定义(参考AI让生活更美好) gcc(GNU Compiler Collection)是一个编译器集合,最初是为C语言设计的,但…

fl studio mobile2024最新官方版V4.6.8安卓版+iOS苹果版

fl studio mobile,一款非常好用的音乐制作软件。该软件具有丰富多样的音乐类型让大家选择,内置多个好用的编辑工具、渲染工具、特效工具等可以使用。用户可以自由使用软件中的任何道具,直接在手机上编曲,进行音乐创作,…

iOS工程:获取手机相册权限,iOS原生系统弹窗, Privacy隐私政策选择,如何添加系统弹出并修改描述文字

【iOS工程】获取手机相册权限,iOS原生系统弹窗, Privacy隐私政策选择,如何添加系统弹出并修改描述文字 设备/引擎:Mac(11.6)/Mac Mini 开发工具:Xcode(15.0.1) 开发需求&#xff…

【Gaussian splatting系列学习】(三)

3DGS系列(一) 3DGS系列(二) 3DGS系列(三) 3D高斯球的颜色 基函数: 任何一个周期性函数可以分解为正弦和余弦的线性组合 球谐函数: 任何一个球面坐标的函数可以用多个球谐函数来近…

游戏引擎详解——图片

图片 图片的格式 图片文件格式pngjpg 纹理压缩格式ETC1/2PVRTCASTC 图片的属性 图片属性解释分辨率宽高像素值(pt),如:1024*1024位深度用来存储像素颜色的值,如RGBA8888,红黄蓝透明度4个维度每个8bit&…

CentOS Docker搭建Mysql5.7集群

MySQL Replication MySQL提供了Replication功能,可以实现将一个数据库的数据同步到多台其他数据库。前者通常称之为主库(master),后者则被称从库(slave)。MySQL复制过程采用异步方式,但延时非常…

初始redis:Zset有序集合

Set作为集合,有两个特点:唯一且无序。 Zset是有序集合,在保证唯一的情况下,是根据什么来排序的呢?排序的规则是什么? Zset中的member引入了一个属性,分数(score)&#…

立式报工台助力MES系统打造智能硬件解决方案

信息化与自动化的深度结合,使得企业在生产效率、质量控制以及资源管理等方面得以大幅提升。制造执行系统MES作为连接企业管理层与生产现场的重要桥梁,正在愈发得到重视。为了进一步强化MES系统的功能与应用,立式报工台作为一种新兴的智能硬件…

适用于 Windows 10 的最佳数据恢复免费软件是什么?

有没有适用于 Windows 10 的真正数据恢复免费软件?这篇文章将讨论这个话题,并分享什么是适用于 Windows 10/11/8.1/8/7/Vista/XP 的最佳数据恢复工具。 有没有适用于 Windows 10 的真正免费的数据恢复软件? 丢失重要数据,无论是由…

RISC-V vector(1) --- vector的引入与register说明

Vector相较于SIMD的优势 这两种实现方案,都是为了实现数据级并行性(存在大量的数据可供程序同时计算); SIMD(Single Instruction Multiple Data) SIMD是将数据宽度和操作类型,都放在了指令中&a…

一道xss题目--intigriti-0422-XSS-Challenge-Write-up

目录 进入挑战 js代码 代码分析 构造payload ​编辑 结果 进入挑战 Intigriti April Challenge题目地址 打开题目后&#xff0c;找到对应页面的js代码&#xff0c;寻找一下我们用户可控的点 js代码 <!DOCTYPE html> <html lang"en"><head> …

[GKCTF 2021]excel 骚操作1

使用010editor打开发现zip头&#xff0c;改后缀名xlsx为zip&#xff0c;解压&#xff0c;在D:\python\flag (1)\xl\worksheets目录下有个sheet1.xml就是ecxel的sheet1的主要样式style 看到很多c r"B2" s"1&#xff0c;只是单元格数据不同而已 &#xff0c;还有的…

Awesome-LLMs-for-Video-Understanding - 基于大型语言模型的视频理解研究

Awesome-LLMs-for-Video-Understanding 是 基于大型语言模型的视频理解研究 github : https://github.com/yunlong10/Awesome-LLMs-for-Video-Understandingpaper&#xff1a;Video Understanding with Large Language Models: A Survey https://arxiv.org/pdf/2312.17432 视频…

C++20中的约束与概念

类模板、函数模板和非模板函数(通常是类模板的成员)可能与约束(constraint)相关联&#xff0c;该约束指定对模板参数的要求(requirements)&#xff0c;可用于选择最合适的函数重载和模板特化。约束是使用模板时需要通过模板参数满足的条件或要求。这些要求的命名集合称为概念(c…

Hadoop 分布式集群搭建

HDFS分布式集群搭建 一、部署规划1.1 进程规划1.2 软件规划1.3 用户规划1.4 目录规划 二、 搭建HDFS 分布式集群2.1 HDFS 集群配置2.1.1 下载安装 Hadoop2.1.2 修改 hadoop-env.sh 配置文件2.1.3 修改 core-site.xml 配置文件2.1.4 修改 hdfs-site.xml 配置文件2.1.5 修改 slav…

程序员:全栈的痛你不知道

上周一个同事直接对我开喷&#xff0c;骂我无能&#xff0c;说&#xff1a;“你怎么一个人就搞不定所有系统呢&#xff1f;”&#xff0c;我半支烟纵横IT江湖14余年&#xff0c;还是第一次被人这么嫌弃。 事情缘由 某公司的业务线特别多&#xff0c;有个业务线前后端项目共计…

ComfyUI IPAdapter plus的模型应该怎么装-免费版-2024.8.25

&#x1f386;背景 ipadapter相关的节点大家应该都不陌生&#xff0c;具体是做什么的就不详细介绍了&#xff0c;但是还是有很多新入门的朋友不太了解这个节点相关的这一堆模型到底应该怎么安装。这里就借着官方节点的介绍来大概讲下这个话题。 涉及到的节点源地址&#xff1…

【Qt】Qt系统 | Qt事件| 鼠标事件

文章目录 鼠标事件鼠标点击事件鼠标释放事件鼠标双击事件鼠标移动事件 滚轮事件 在 Qt 中&#xff0c;鼠标事件是用 QMouseEvent 实现的。当在窗口中按下鼠标或者移动鼠标时&#xff0c;都会产生鼠标事件 鼠标事件 鼠标点击事件 鼠标按下时通过 虚函数 mousePressEvent() 来…

线程安全是什么问题?如何引起?死锁是啥?如何解决?

目录 一、什么是线程不安全&#xff1f; 二、如何引起的线程安全&#xff1f;怎么解决&#xff1f; 1&#xff09;CPU调度执行是随机的&#xff0c;抢占式执行&#xff08;根本原因&#xff0c;硬件层面咱们无法干预&#xff09; 2&#xff09;多个线程&#xff0c;对同一变…