换个思路快速上手UML和plantUML——时序图

上一章我们介绍了类图,我们很清楚,类图是从更加宏观的角度去梳理系统结构的,从类图中我们可以获取到类与类之间:继承,实现等关系信息,是宏观逻辑。下面我们继续换一个思路:作为一名软件工程结构化图的设计者去设计另一种图,要求:

1)这种图要微观的体现调用关系

2)要线性的体现调用的时间关系

3)要能体现不同逻辑的不同结果

而这种图主要用于阅读源码,或者向别人介绍代码思路的等等相关的场景。

在这里插入图片描述

1.入手代码

对比设计类图,这个微观一点图显然要更加复杂,为了能成功把这种图设计出来,所以我们从实际的一段代码出发

package se;
/*** @author: Jeffrey* @date: 2024/01/29/11:06* @description:*/
public class TimeSequenceUML {public static void main(String[] args) {Client client = new Client();client.work();}
}
class Device{public void write(String hello) {}
}
class Server{private Device device;public void close() {}public void open() {}public void print(String hello) {device.write(hello);}
}class Client{private Server server;public void work(){server.open();server.print("hello");server.close();}
}

2.代码分析

2.1 图的元素

这段代码并不难理解,调用关系也并不复杂,如果直接去像我们平时阅读源码的思路一样去走方法,可以得到一个线性的调用思路,但是我们经常会遇到这么几个问题:

  1. 代码的核心对象是谁?
  2. 代码的调用者是谁?
  3. 都是对象,这些对象的之间各自承担的逻辑任务其实很容易搞混

说白了:为了设计好这个图,我们要完成的第一件事就是把这些代码的元素抽象出来,用一个图形表示就好了。于是优秀的我们思考了很多相关的对象完成以下的元素设计:

元素:含义:图像:plantUml:
角色一般是逻辑的开始交互者,可以是:人,机器,系统image-20240129115711016actor name
对象一般是逻辑的中间参与者,一般代表对象,又可以改变形状为以下具体的类型image-20240129115932546participant client
实体image-20240129120139844entity name
控制image-20240129120208121control name
数据库image-20240129120216366database name
集合image-20240129120222746collections name
队列image-20240129120228971queue name
边界image-20240129120235244boundary name

2.2 图的结构

将对象抽象出来后,下一步我们必须要考虑的就是如何将这些对象组织起来:

学习过线程进程,操作系统,计算机体系结构中任何一门课程的朋友们都知道:我们感觉计算机的某个操作是一瞬间的事情,其实它经历了很多个线性阶段,即使是多核多处理器的计算机,也是由一个个线性的阶段和并行的阶段链接而成,如何让我们简单明了的直接看图就能看懂程序?那么就要在图中体现程序的线性和并行关系

可是连接起来之后,不得不考虑的一个问题就是元素和元素要怎么摆放?如何才能同时体现一段时间内在调用时间上的线性特征一个瞬间时方法调用的顺序线性特征

聪明的我们明白,是时候定下一些规则来了!

  1. 关系越紧密,交互越密集的元素要尽可能的放到越近的地方
  2. 我们定义一个坐标轴,纵向代表时间顺序的线性关系
  3. 横向代表一瞬间方法调用的线性关系,或者说方法调用的层次关系

image-20240129160639721

2.3 消息和生命周期

看看我们现在有什么?有元素,有规则,下一步就是把调用顺序放进去了!记得黑盒模型吗?我们知道封装的思想有一部分就是为了隐藏方法的具体实现细节,我们现在主要关注的是方法的顺序,我们可以把每个调用过程当作是一个黑盒,只关注黑盒的输入输出信息。

我们用:

image-20240129161048506

实线实箭头来表示调用,用虚线实箭头来表示返回信息

在PlantUML中:
-> 实线
--> 虚线

image-20240129161720713

消息已经做好了,回到我们的需求,我们需要反应每个对象在什么阶段是激活的,在什么时候就跟这个对象没有什么关系了。

但是这里我们要注意一个区别,对于Java 来说,大家都知道基于JVM,对象的回收一般是不由我们来负责的【我们负责的主要是一些系统的接口或者说一些通道/流的开关】,而在UML中也类似,对象的激活状态代表的不是如IOC中对象一直的在内存中/在容器中,而是代表:在一个对象工作的同时,另一个对象是否在工作?如果在工作,表示为激活,反之为不活跃。

也就是说:我们要反映同一时刻对象的活跃状态

考虑到生命周期和时间是线性相关的,我们用在对象上的长矩形来体现生命周期的长短

image-20240129162448097

用横向上的矩形在同一水平来表示同时刻不同对象的活跃状态

image-20240129162726726

进一步的完善我们的图:

image-20240129162851557

2.4补充语法

至此我们已经能基本完成一个简单代码的线性过程,为了方便我们的绘图和绘制更加直观的图,我们补充一部分PlantUML的语法:

2.4.1 组合片段
ALT

抉择组合片段 ALT:说白了就是要在图中体现IF-ELSE 逻辑
比如这串代码:

package se;/*** @author: Jeffrey* @date: 2024/01/23/21:55* @description:*/
public class Test {public static void main(String[] args) {Student student = new Student();if (student.isGender()){Mapper mysql = new MySqlMapper();mysql.insert(student);}else {Mapper sqlServer =new SqlserverMapper();sqlServer.insert(student);}}
}
class Student{private boolean gender = true;public boolean isGender() {return gender;}
}
interface Mapper{public void insert(Student student);
}
class MySqlMapper implements Mapper{@Overridepublic void insert(Student student) {//持久化到Mysql}
}
class SqlserverMapper implements Mapper{@Overridepublic void insert(Student student) {//持久化到SqlServer}
}

可以绘制为:

image-20240129165049761

如果用plant UML 来表示:

@startuml
actor wo
Participant Test
Participant Student
Participant MySqlMapper
Participant SqlserverMapperautonumber
wo -> Test : main()
Test -> Student: isGender()
activate Student
alt Gender == trueStudent -> MySqlMapper:insert()activate MySqlMapperMySqlMapper --> Studentdeactivate MySqlMapper
elseStudent -> SqlserverMapper:insert()activate SqlserverMapperSqlserverMapper --> Studentdeactivate SqlserverMapper
end
Student --> Test
deactivate Student
@enduml

补充:

  1. 在plantUML 中if-else 逻辑通过 alt /else 来表示,如果需要else if,只需要再添加一个else,同时这个组合片段必须用end 来结尾
  2. 一般当向一个对象发出消息时,这个对象被激活,进入生命周期,返回消息时被置为不活跃状态,所以我在发完消息后用activate name 来激活对象,在回复完消息后用 deactivate name
  3. autonumber 可以用于自动对消息进行编号
  4. 还可以在第一条消息发送前用autoactivate on 来自动填充activate,然后每次需要返回消息时用return 代替:

综上可优化为:

autonumber
autoactivate on
wo -> Test : main()
Test -> Student: isGender()
activate Student
alt Gender == trueStudent -> MySqlMapper:insert()return
elseStudent -> SqlserverMapper:insert()return
end
return
Loop

显然这可用于代表循环

loop 1000 timesStudent -> SqlserverMapper:insert()returnend

image-20240129170046241

Group

可直接简单用于将一部分逻辑框起来,再添加对应的注释

    group SqlServer逻辑单元 [数据持久化]Student -> SqlserverMapper:insert()returnend

image-20240129170412126

2.4.2 逻辑分割/分隔符

可以将一块代码分割成若干逻辑模块/或者代码分层:

wo -> Test : main()
Test -> Student: isGender()
==初始化==
alt Gender == trueStudent -> MySqlMapper:insert()return
elsegroup SqlServer逻辑单元 [数据持久化]Student -> SqlserverMapper:insert()returnend
end
==持久层==

image-20240129170653321

2.4.3 让响应信息显示在箭头下面

可以使用skinparam responseMessageBelowArrow true命令,让响应信息显示在箭头下面。

2.4.4 增加彼此空间

可以使用|||来增加空间。

@startuml
Alice -> Bob: message 1
Bob --> Alice: ok
|||
Alice -> Bob: message 2
Bob --> Alice: ok
||45||
Alice -> Bob: message 3
Bob --> Alice: ok
@enduml

image-20240129170856693

2.4.5 包裹参与者

可以使用boxend box画一个盒子将参与者包裹起来。

2.4.5 并行

可以使用parend par 来将同一时间段并行逻辑括起来

3.代码实战

我们用之前我写的一个简单Netty 实现的servlet 容器的代码来进行一次简单的项目实战,源码地址是:

Netty实现简易tomcat容器

大概整体项目并不规范的时序思路是这样的:

img

这个项目实现的基本功能就是根据自定义协议传入网页请求信息,实现对信息的解码,并包装成实现了HttpServlet 接口的容器。

而我们的目标就是用时序图来完成从HelloServlet收到一个登录请求的调用过程的绘图:

业务层

@startuml
autonumber
autoactivate on
Actor browser as br
Participant HelloServlet as hs
Participant HttpServletRequest as req
Participant UserService as us
br -> hs:dePost(req,rep)
hs->req:getParameter(username)
return String:username
hs->req:getParameter(password)
return String:password
hs->us:login(username,password)
return false
return response
@enduml

image-20240129222907980

本篇关键词:时间顺序,方法调用顺序,生命周期=激活状态

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

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

相关文章

给刚上小学的侄女准备新年礼物,有什么让小朋友喜欢的玩具推荐?

给刚上小学的侄女准备新年礼物,我觉得也是有很多选择的。因为现在的市场上款式太多了,选择自己心意的适合小侄女的都是可以的。但是如果非要选益智的或是智能高科技的,对孩子来说既能玩耍又能在玩的同时学习到知识,能够开拓孩子眼…

无限可能!安全狗入选“潜力十强企业”

近日,等级保护测评公布了“2023年网络安全优秀评选”活动评选结果。 作为国内云原生安全领导厂商,安全狗凭借突出的综合实力,荣获“潜力十强企业”称号。 厦门服云信息科技有限公司(品牌名:安全狗)创办于20…

《HTML 简易速速上手小册》第10章:HTML 的维护与优化(2024 最新版)

文章目录 10.1 网页性能优化10.1.1 基础知识10.1.2 案例 1:优化网页图像10.1.3 案例 2:使用延迟加载优化性能10.1.4 案例 3:优化 CSS 和 JavaScript 的加载 10.2 SEO 最佳实践10.2.1 基础知识10.2.2 案例 1:创建一个 SEO 友好的博…

数据库管理-第139期 做大还是做小-Oracle名称哪些事(20240125)

数据库管理139期 2024-01-25 第139期 做大还是做小-Oracle名称哪些事(20240125)1 问题2 排查3 扩展总结 第139期 做大还是做小-Oracle名称哪些事(20240125) 作者:胖头鱼的鱼缸(尹海文) Oracle A…

麒麟系统—— openKylin 安装 mongodb

麒麟系统—— openKylin 安装 mongodb 一、准备工作1. 确保麒麟系统 openKylin 已经安装完毕。 二、下载解压 MongoDB二、增加环境变量三、配置MongoDB创建数据目录创建日志文件运行 四、加入到服务中 MongoDB是一款高性能、开源的NoSQL数据库,因其灵活的数据结构、…

MyBatis 的注解实现方法

MyBatis 的注解实现方法 MyBatis 的注解实现方法引入依赖添加配置创建表创建实体类创建mapper接口InsertDeleteSelectResults和ResultMap通过配置文件解决 UpdateOptions MyBatis 的注解实现方法 引入依赖 在springBoot项目中下载了EditStarters插件的,可以直接在配置文件处右…

效率高的B树系列

文章目录 前言B树概念性质插入数据分析代码实现性能分析 B树概念特性插入数据分析应用 B*树概念B*树的分裂 总结B树系列的区别B树系列对比哈希和平衡搜索树 前言 前面我们所学习到的数据结构,只能用来存储少量的数据,因为内存大小是非常有限的&#xff…

.ui文件相关

目录 ui类生成过程: 提问: 等以后自己熟练了用代码写这些样式内容,尽量用代码写,原因很简单: 用代码写的可以直接修改代码,但是在设计界面修改的东西,电脑没有QC这玩意,还真不好改…

Gitlab7.14 中文版安装教程

Gitlab7.14 中文版安装教程 注: 本教程由羞涩梦整理同步发布,本人技术分享站点:blog.hukanfa.com转发本文请备注原文链接,本文内容整理日期:2024-01-28csdn 博客名称:五维空间-影子,欢迎关注 …

JWT(JSON Web Token)详解以及在go-zero中配置的方法

目的 对用户进行身份认证和信息交换 RFC 7519 传统方式 通过session保存对话信息,服务端返回一个session id,用户保存这个id在cookie内,然后每次请求都传给服务端 局限性 对于服务器集群难以向每个服务器共享同一session jwt的方式是…

【vue】vue.config.js里面获取本机ip:

文章目录 一、效果:二、实现: 一、效果: 二、实现: const os require(os);function getLocalIpAddress() {const interfaces os.networkInterfaces();for (let key in interfaces) {const iface interfaces[key];for (let i …

第九节HarmonyOS 常用基础组件16-Blank

1、描述 空白填充组件,在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。仅当父组件为Row/Column/Flex时生效。 2、接口 Blank(min?: number | string) 3、参数 参数名 参数类型 必填 描述 min number|string 否 空白填充组件…

数据分析入门指南:用 Python 开启数据之旅

文章目录 前言发现宝藏为什么选择 Python 进行数据分析?准备工作数据分析基础1. 数据加载2. 数据探索3. 数据清洗4. 数据可视化 探索更多可能性好书推荐总结 前言 为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。…

成都直播产业园核心优势全面解读,入驻天府锋巢直播产业基地都有哪些好处?

一文讲清!成都直播产业园核心优势全面解读 企业入驻天府锋巢直播产业基地能获得哪些好处? 锋巢资讯~又来了~~~ 今天,将为您全面解读成都产业园重点特色产业服务(上) 什…

Android 13以上版本读写SD卡权限适配

如题&#xff0c;最近工作上处理的问题&#xff0c;把解决方案简单逻列出来&#xff0c;供有需要的朋友参考之 解决方案&#xff1a; 1、配置权限 <uses-permission android:name"android.permission.READ_MEDIA_IMAGES" /><uses-permission android:name&q…

(自用)learnOpenGL学习总结-高级OpenGL-立方体贴图

ok终于来到了立方体贴图了&#xff0c;在这里面我们可以加入好看的天空包围盒&#xff0c;这样的画我们的背景就不再是黑色的了&#xff01; 首先&#xff0c;立方体贴图和前面的sampler2D贴图一样&#xff0c;不过是6个2D组成的立方体而已。 那么为什么要把6个组合在一起呢&…

树莓派部署Nginx服务结合内网穿透实现远程访问本地站点

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 安装 Nginx&#xff08;发音为“engine-x”&#xff09;可以将您的树莓派变成一个强大的 Web 服务器&#xff0c;可以用于托管网站或 Web 应用程序。相比其他 Web 服务器&#xff0c;Ngi…

怎样用流程自定义表单提升办公效率?

如果想要提升办公协作效率&#xff0c;可以试试低代码技术平台及流程自定义表单工具。不可否认的是&#xff0c;随着社会的进步和发展&#xff0c;传统的表单制作工具已经没有办法再满足业务量不断上涨的办公需求了&#xff0c;但是&#xff0c;借助专业的流程自定义表单工具就…

AES 加解密python实现

1. 要求 编程实现AES-128的加解密算法&#xff0c;满足给定明文和密钥加密得到密文&#xff0c;给定密文和密钥解密得到明文&#xff0c;最终用界面化的形式呈现。 2. 算法流程 程序主要分为加密与解密两个大模块。在加密模块中包括四个小模块&#xff0c;分别为轮密钥加、字…