《软件方法(下)》8.3 建模步骤C-2 识别类的关系(202405更新)

DDD领域驱动设计批评文集

做强化自测题获得“软件方法建模师”称号

《软件方法》各章合集


8.3 建模步骤C-2 识别类的关系

首先重复本章开头所提到的:

虽然本书先讲解“识别类和属性”,再讲解“识别类的关系”,但在实际工作中,先“识别类和属性”再“识别类的关系”这个思考顺序只是一个微小的思考周期内的顺序。建模一张类图,需要很多个思考周期。也就是说,识别类和属性→识别类的关系→识别类和属性→识别类的关系→……是交错进行的。

我们阅读用例规约或其他素材,一边思考一边建模,不管识别出类、属性还是关系,画上去就是,并不需要假装看不见类的关系,非得先把类和属性都识别完了,再来识别类的关系。

8.3.1 类的关系

类的关系有三种:泛化(Generalization)、关联(Association)和依赖(Dependency),UML表示法如图8-80。

图片

图8-80 类的关系

泛化和关联是类的静态关系。这是系统要想办法记住的关系,或者说,这两个关系属于系统要维护的“数据”。即使系统当前没有运行需要用到这些关系的用例,这些关系依然存在,随时等待着被“使用”。

泛化表示集合关系。两个类形成泛化,意味着超类的对象集合包含子类的对象集合。B、C泛化到A(或者说,B、C继承自A),意味着A的对象集合包含B和C的对象集合,如图8-81。

图片

图8-81 泛化表示集合关系

★也可以换一种说法:子类的特征集合包含超类的特征集合。

由于是集合关系,泛化关系是没有1对多、多对多等多重性的。

任何集合都是本身的子集,但此处的“包含”不考虑这种情况,也就是说,泛化的“包含”指真子集的“包含”。泛化关系只能发生在不同的类之间,不能同一个类形成自反泛化,否则就会导致批量刷废话——每个类都无条件地刷一个自反泛化。

间接的“自反泛化”也是不允许的,A的子类或子类的子类不能成为A的超类。也就是说,泛化关系是传递和非对称的:对象集合A、B、C,如果A⊃B,B⊃C,那么可以得出A⊃C,而且C⊅B,C⊅A,B⊅A。

如图8-82的情况,都是不允许的:

图片

图8-82 不允许的泛化关系

关联表示个体关系。关联可以发生在不同类之间,也可以发生在同一个类之间,意味着类的对象个体之间有关系。

如图8-83的左侧,A和B、C关联,意味着某个A的个体可能会和某些B和C的个体有关系;

如图8-83的右侧,A自己和自己关联,意味着某个A的个体可能会和另外的A个体有关系。

图片

图8-83 关联表示个体关系

因为关联是类的对象个体之间的关系,所以会有1对多、多对多等多重性,甚至在某些情况下存在同一个类自己和自己的关联——自反关联。

是集合关系还是个体关系,这是泛化和关联的本质区别,从自然语言的表达来推断有时是不可靠的。

例如,自然语言"人有男有女"说的是泛化关系。"人有男有女"的意思不是一个人的个体里有若干男人个体和若干女人个体,而是说人的对象集合包含了男人的对象集合和女人的对象集合。

自然语言"人有手有脚"说的是关联关系。"人有手有脚"的意思不是人的对象集合包含了手、脚的对象集合,而是说一个人的个体组装了若干手和脚的个体。

读者可以自行体会一下“人有车有房”和“人有高富帅有屌丝”的区别。

对于比较熟悉的领域,例如刚才的男女、手脚,拍脑袋就可以知道是泛化还是关联,那拍脑袋就可以了。如果进入陌生的领域,回溯到集合和个体的本质区别是必要的。

泛化和关联的进一步内容,后文还会单独分节讲述。

再来看依赖关系:

如果类B变化,类A也需要变化,那么可以认为类A依赖于类B。

从这个定义来看,泛化和关联也是依赖关系。泛化是子类依赖于超类,关联的依赖看关联的方向。不过,泛化和关联有另外的表示法,所以一般说的依赖指除了泛化和关联之外的其他依赖,例如调用、实例化等。

类之间的依赖关系用带箭头的虚线表示,线上可以标注依赖的类型(可选),如图8-84:

图片

图8-84 类之间的依赖

★显然,只有在信息系统的分析或设计模型中才会出现调用、实例化等依赖关系,纯粹描述领域知识的领域模型是不需要的。

这些依赖关系并非时刻都存在,而是在信息系统执行某个用例的某个步骤时才会产生,而且持续的时间非常短——从分析工作流的假设来说,就是趋近于0。因此,要描述依赖关系,仅在类图上描述“A依赖于B”是不够的,还要具体到某个场景。

例如,要描述A会调用B、C的操作,如图8-85在类图上画依赖的虚线箭头,不是不可以,但还不够。

图片

图8-85 在类图上表达“A依赖于B、C”还不够

应该在某个用例的某张序列图(或通信图)上描述,在什么场景,进行到哪个步骤时,A需要调用B的什么操作,在什么场景,进行到哪个步骤时,A需要调用C的什么操作,如图8-86。

图片

 图8-86 “A会调用B、C”应在序列图上表达

有了序列图,如图8-85的类图上的依赖虚线就没有必要画出来了,类图上画泛化和关联关系即可。

经常看到这样的类图:上面布满了依赖的虚线,却没有泛化和关联,如图8-87。如果这样的类图描述的是不同领域的类之间的协作,那还可以接受,如果类图上都是核心域的概念,那就要警惕了,可能建模人员根本没有去寻找泛化和关联关系。

图片

图8-87 只有依赖关系的类图

也许有的读者会想,图8-87这不挺规整的嘛!问题就在于,依赖关系为什么是这个样子,很可能是没有依据的。建模人员拍脑袋定了这样的依赖关系,然后就假装自己已经“建模”了。

如图8-88,有ABCD四个类,可以随意编排它们之间的依赖,不管哪一种,都可以写出代码来,编译器也不会报错。但哪一种更合理,要尽量从静态关系来找依据。

图片

图8-88 没有依据,依赖可以随意编排

时不时会有开发人员向我介绍他所做系统的“架构”,“您看,A调用B,B调用C……”,然后就没了。为什么要这样调用,也讲不出什么理由,反正我就是这样做了,而且做出来了,好像也能用,就行了呗,管它洪水滔天!

8.3.2 识别泛化关系

8.3.2.1 识别泛化的思路

(1)直接形成

类图中的两个类可能会直接形成泛化关系,如图8-89所示。严格的做法是针对每两个类,思考“A是B的一种吗?”,再反过来思考“B是A的一种吗?”不过这样做工作量很大。类图中有n个类,就需要思考2C(n,2)=n(n-1)次。n=11时,就是110次了!实际工作中,往往是先扫描一遍,大脑迅速过滤出可能值得这样思考的类,针对这些类思考即可。

图片

图8-89 直接形成-两个类之间直接形成泛化关系

实际上,类图上已有的两个类有泛化关系但未识别的情况并不多,因为之前从用例规约识别类和属性时很有可能已经发现了。

(2)自下而上(从特殊到一般)

更多的情况是发现类图上已有的两个或多个类有共同特征,于是抽象出共同的超类,如图8-90所示。

图片

图8-90 自下而上-两个类之上有共同的超类

关联也可以看作类的属性,关联的角色名相当于类的属性名称。如果多个类关联到同一个类而且角色名相同,也可以考虑泛化出共同的超类,如图8-91。注意,角色名要相同,否则即使类型相同也不是同一属性。

图片

图8-91 共同的关联也可以提炼超类

(3)自上而下(从一般到特殊)

如图8-92所示,这个识别思路就是8.2.5.6 属性是否对所有对象都有意义里的思路,此处就不再赘述。

图片

图8-92 自上而下-一个类分裂出子类

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库管理-第184期 23ai:干掉MongoDB的不一定是另一个JSON数据库(20240507)

数据库管理184期 2024-05-07 数据库管理-第184期 23ai:干掉MongoDB的不一定是另一个JSON数据库(20240507)1 JSON需求2 关系型表设计3 JSON关系型二元性视图3 查询视图总结 数据库管理-第184期 23ai:干掉MongoDB的不一定是另一个JSON数据库(20…

9.4k Star!MemGPT:伯克利大学最新开源、将LLM作为操作系统、无限上下文记忆、服务化部署自定义Agent

9.4k Star!MemGPT:伯克利大学最新开源、将LLM作为操作系统、无限上下文记忆、服务化部署自定义Agent 原创 Aitrainee | 公众号:AI进修生:AI算法工程师 / Prompt工程师 / ROS机器人开发者 | 分享AI动态与算法应用资讯,提…

人脸采集训练识别

项目概述: 本地摄像头采集人脸数据集,通过训练得到trainingData.yml模型,加载haarcascade_frontalface_default.xml实现人脸识别。haarcascade_frontalface_default.xml 文件并不是一个完整的人脸识别模型,而是一个用于检测正脸&a…

Conda安装rasterio报错

Conda安装rasterio报错 文章目录 Conda安装rasterio报错问题解决参考 问题 在conda环境中安装rasterio包之后,本来可以正常运行的,但是之后又重新安装了一个gdal,导致原来的引用rasterio的包的程序不可正常运行了 conda install rasterio c…

流畅的python-学习笔记_序列

概念 抽象基类:ABC, Abstract Base Class,ABC还有一个概念,是一个编程语言 序列 内置序列类型 分类 可分为容器类型和扁平类型 容器类型有list, tuple, collections.deque等,存储元素类型可不同&…

分布式架构|打造高效、稳定、灵活的现代IT基石

分布式架构:打造高效、稳定、灵活的现代IT基石 一、独立扩展:应对业务增长与用户激增二、高可用性:确保系统稳定运行三、可维护性:降低系统复杂性四、技术选型灵活性:充分利用各种技术优势五、数据隔离与安全性 随着信…

基于Springboot+Vue的Java项目-旅游网站系统开发实战(附演示视频+源码+LW)

大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &am…

IOS离线打包uniapp的信息时报错如下的解决方法

IOS离线打包uniapp的信息时报错如下的解决方法 问题描述: Extract app intents metadata 0.1 seconds XExtractAppIntentsMetadata(in target HBuilder from project HBuilder-Hello)cd /Users/whb/space/vpt/vptios/HBuilder-Hello/Applications/Xcode.app/Conte…

音视频开发3 视频基础,图片基础

图片像素(Pixel) 一张图片是由多少个 像素 构成的。 例如一张图片是由60x50组成的。 位深度 bit depth RGB表示法 红(Red)、绿(Green)、蓝(Blue) 除了24bit,常见的位深…

(41)5.6-5.7数据结构(栈和队列的应用)

1.栈在括号匹配中的应用 #define _CRT_SECURE_NO_WARNINGS #define MaxSize 10 typedef struct { char data[MaxSize];//静态数组存放栈中元素 int top; //栈顶指针 }SqStack;//初始化栈 void InitStack(SqStack& S);//判断栈是否为空 bool StackEmpty(SqStack S…

寻找身高最相近的小朋友 - 华为OD统一考试(D卷)

OD统一考试(D卷) 分值: 100分 题解: Java / Python / C++ 题目描述 小明今年升学到小学一年级,来到新班级后发现其他小朋友们身高参差不齐,然后就想基于各小朋友和自己的身高差对他们进行排序,请帮他实现排序。 输入描述 第一行为正整数H和N,0<H<200,为小明的…

C++ | Leetcode C++题解之第72题编辑距离

题目&#xff1a; 题解&#xff1a; class Solution { public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size() 1, vector<int>(word2.size() 1, 0));for (int i 0; i < word1.size(); i) dp[i][0] i;for (int j…

公钥私钥?一文搞懂非对称加密

非对称加密 非对称加密&#xff1a; 通信双方分别创建公钥和私钥&#xff0c;并且保证公钥所加密的信息&#xff0c;只有配对的私钥可以解密&#xff0c;接下来&#xff0c;双方公开交换公钥&#xff0c;通信时&#xff0c;使用对方的公钥进行加密&#xff0c;如此&#xff0…

基于51单片机无线恒温箱恒温控制系统

基于51单片机无线恒温箱恒温控制 &#xff08;程序&#xff0b;原理图&#xff0b;PCB&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.DS18B20温度传感器测温。 2.按键可以设定温度上下限及温度刷新时间间隔。 3.使用NRF24L01无线模块传输数据 4.温度…

flask网站开发计划

我想写一个flask开发网站的合集文章&#xff0c;该网站主要是采集网络上的文章&#xff08;不同站点&#xff0c;用Python识别出正文内容&#xff09;&#xff0c;然后做成长图形式&#xff0c;发布到flask站点&#xff0c;并提供“下载”按钮&#xff0c;点击下载按钮&#xf…

第3章 WebServer重构

3.1 重构原生Web服务框架 3.1.1 分析原生Web服务框架 在服务端代码的 ClientHandler 中&#xff0c;请求解析、处理请求、返回响应的代码混杂在一起&#xff0c;这样的设计会导致代码难以维护和理解。为了提高代码的可读性、可维护性和可扩展性&#xff0c;我们需要对这些代码…

快速掌握Redis优化要点,告别性能瓶颈!

大家好!我是小米,今天和大家分享一下在Redis中如何进行优化,以提升系统性能。Redis作为一种流行的内存数据库,因其高性能、高可用和数据持久性而受到广泛应用。然而,在实际应用中,我们仍需对Redis进行优化,以满足各种业务需求。接下来,我将从读写方式、KV size、Key数量…

VALSE 2024主旨报告内容解析:以深度学习框架为牵引促进自主AI生态发展

2024年视觉与学习青年学者研讨会&#xff08;VALSE 2024&#xff09;于5月5日到7日在重庆悦来国际会议中心举行。本公众号将全方位地对会议的热点进行报道&#xff0c;方便广大读者跟踪和了解人工智能的前沿理论和技术。欢迎广大读者对文章进行关注、阅读和转发。文章是对报告人…

探秘Flex布局下子元素宽度超出的那些烦心事

嘿&#xff0c;小伙伴们&#xff01;你们有没有遇到过用Flex布局的时候&#xff0c;子元素的宽度莫名其妙地超出了父元素的情况&#xff1f;别着急&#xff0c;今天我就来给大家揭秘这个问题的来龙去脉&#xff0c;以及一些解决方案。让我们一起来深入探讨&#xff01; 发现问…

【Gaea+UE5】创建基本的大型世界场景

目录 效果 步骤 一、在Gaea中生成地形 二、确定导出的地形规模 三、在UE中创建地形 四、验证UE创建的地形规模是否正确 五、使用M4自动地形材质 效果 步骤 一、在Gaea中生成地形 1. 打开Gaea官网下载软件 2. 打开Gaea软件&#xff0c;我们可以选择一个预设的山体 创…
最新文章