[!success] 软件开发没有银弹

前置知识

序列图/时序图

  • 时序图更加适合设计多个微服务多方调用,活动图更加适合一个部分逻辑复杂使用
  • 异步调用用空心箭头,同步用实心箭头
  • 返回值统一用虚线表示
  • 交互框:实际上就opt,alt,loop,par常用
  • 序列图场景
应用场景名称抽象级别示例作用
业务建模业务序列图组织-组织
系统-系统
业务执行者、业务工人、业务实体业务用例的实现,描述组织内业务流程
设计设计序列图系统-系统
组件-组件
组件组织的各种系统如何协作以完成组织的用例

[!tip] 参考 https://diangroup.feishu.cn/file/TfE7bFToQo2tDOxEPmSc07UhnTe https://zhuanlan.zhihu.com/p/422509874

活动图

活动图的前身流程图,应该是在建模人员中使用频率最高的图形了。流程图最早出现于1921年Gilbreth的文章中,用于机械工程领域。在Goldstine和von Neumann将其引入计算机领域之后,流程图变得流行起来,主要用于在编写文本源代码之前表达跳转逻辑。不过,随着编程语言表达能力越来越强,针对简单的分支或循环逻辑画图在很多情况下已经变得没有必要

  • 之前画得基本上都是活动图,着重于数据在各个组件之间的传递,这个有点相当于业务序列图和设计序列图的结合版本,核心在于数据的传递,以及传递过程的组件
  • 这种理解性最好,推荐系统需要画一个

[!tip] 参考 UML活动图大白话入门教程 - 知乎

软件工作流

  1. 业务建模:描述的是整个领域内的系统如何协作不只是要开发的部分
  2. 需求:想要的功能特性
  3. 分析: 分析该什么做
  4. 设计:具体的逻辑实现等等

业务建模

[!important] 作用 描述组织内部各系统(人脑系统、电脑系统……)如何协作,使得组织可以为其他组织提供有价值的服务。新系统只不过是组织为了对外提供更好的服务,对自己的内部重新设计而购买的一个零件

愿景

业务序列图

  • 序列图描绘的是业务,因此每个对象是一个系统而不是模块,消息代表的是责任而不是数据和逻辑
  • ==消息代表责任分配而不是数据流动==:序列图最重要的要点是消息的含义。A 指向 B 的消息,代表“A 请求 B 做某事”,或者“A 调用 B 做某事的服务”,做某事是 B 的一个责任。比如上图中不能写为'把审批单提交'而是应该写成"审批报销单",审批是B的责任,具体的数据流通过参数传递
  • 每个对象是系统,而不是细化的某个逻辑,过细的自反消息会把需求和分析的工作流的工作带入了业务建模
  • 序列图的返回通常使用虚线,业务序列图很少有返回消息,除非是一整个流程结束才会返回

需求

系统用例图

  • 重点是==对外部的什么个体,提供了业务流程中的什么价值==,系统能够为执行者提供的、涉众可以接受的价值
  • 用例的命名是动宾结构,用例的命名是动宾结构,例如“取现金”。 动词前面可以加状语,宾语前面可以加定语,把一句话 的主语砍掉,剩下的可以作为用例的名字。
  • ==命名是用户提供的价值而不是过程的细节,也不是数据库的增删改查==,例如应该是'开发票'而不是'添加发票','作废发票'而不是'删除发票'

分析

分析一般画得是类图

分析类图

  • 具体例子可以参考 设计模式
  • 分析类的种类
    • 边界类:输入、输出,及简单的过滤
    • 控制类:控制用例流,为实体分配责任
    • 实体类:系统的核心,封装领域逻辑和数据。
    • 执行者先把消息发给边界类对象,边界类对象能(类比于数据库的表)
  • 泛化:类似==面向对象中的继承==,子类通过继承超类而拥有超类的特征,是一种集合关系,如人与男人、女人。识别泛化关系的方法有:
    • 对类与类之间,思考A是否是B的一种,而B是否是A的一种
    • 对多个已有的类,抽象出公共部分,形成超类
    • 从一般的类,细化出特殊的子类
    • 尽量不要跨领域形成泛化关系
  • 关联:对象通过组装其他对象而拥有其他对象的特征,是个体类间的关系,如人与手、脚。只有系统负责维护的关系,才构成关联。泛化和关联,可以视分析场景进行转变,可用于简化模型。关联的形式有:
    • 普通关联(一根直线)
    • 聚合(直线一端是空心菱形):多个对象和某个对象的关联紧密,视为受其影响的分区(如公司与各个部门)
    • 组合(直线一端是实心菱形):比聚合更严格,“部分”对象跟随“整体”对象销毁而销毁;“部分”对象只属于一个“整体”对象;“整体”对象负责“部分对象的创建与销毁。
    • 自反关联,即关联发生在同一个类上
  • 依赖:其他不能视为泛化或关联的类间关系
  • 类的可见性

[!tip] 参考 https://zhuanlan.zhihu.com/p/109655171 https://zhuanlan.zhihu.com/p/149035395

UML关系图

demo

  • 箭头上的数字代表 1 个学生可以不参加课程,也可以无限制参加各种课程
  • 1 代表一个,0..* 代表 0 个到无限个

[!important] 多重性 多重性应用于关联的目标端,说明源类的每个实例与目标类实例的连接个数。 0..*:0个或多个 3..7:指定范围(3~7个,包含3和7)

依赖

  • 对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系。
  • 类 A 使用到了类 B,而这种使用关系具有偶然性,临时性,非常弱的,但是 B 类中的变化会影响到类 A

[!example] 你是一名出租车司机,每天开着公司给你分配的车去载客,而每天出租车可能不同,我只是个司机,公司给我什么车我就开什么车,我使用这个车。

关联

  • 对于两个相对独立的对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联关系。双向关联的话箭头可以省略。
  • 两个类中一种强依赖关系,比如我和我的朋友,这种关系比依赖更强,不存在依赖关系中的偶然性,关系也不是临时的,一般是长期性的。

[!example] 我是一名老司机,车是我自己的,我拥有这辆车,平时也会用着辆车去载客人。

聚合

  • 聚合关系是关联关系的一种,耦合度强于关联,他们的代码表现是相同的,仅仅是在语义上有所区别:关联关系的对象间是相互独立的,而聚合关系的对象之间存在着包容关系,他们之间是“整体-个体”的相互关系。
  • 聚合关系中作为成员变量的类一般使用 set 方法赋值

[!quote] 依赖:用完就扔。
关联,聚合:不属于我,但是用完先放着。
组合:是我的一部分,用完保存好。

组合

  • 相比于聚合,组合是一种耦合度更强的关联关系。存在组合关系的类表示“整体-部分”的关联关系,“整体”负责“部分”的生命周期,他们之间是共生共死的;并且“部分”单独存在时没有任何意义。

[!example] 人和灵魂,身体之间是组合关系,当人的生命周期开始时,必须同时拥有灵魂和肉体,当人的生命周期结束时,灵魂肉体随之消亡;无论是灵魂还是肉体,都不能单独存在,他们必须作为人的组成部分存在。

继承

实现

[!tip] 参考 https://zhuanlan.zhihu.com/p/24576502

彩色建模

  • #TODO 这里可以参考一下彩色建模

设计

DDD领域驱动模型是在这里起作用的

设计序列图

  • 设计序列图描绘的是系统的具体逻辑,是和代码最接近的地方

状态机图

  • 按照下图规范

[!tip] 参考 UML之状态机图 - gd_沐辰 - 博客园

DDD领域驱动

QA

如何确定使用什么图

  • 如果侧重点是一个请求的完整生命流程, 侧重于一个请求的整体链路和大致步骤, 使用时序图, 因为时序图可以看到这个调用方和整个调用流程
  • 如果侧重于某个点的详细复杂逻辑(比如很多判断异步循环)类似 微服务框架,或者某个服务某个接口的详细流程,使用流程图(适合在接口逻辑设计时候使用)
  • 如果是整体架构的层面的设计,观察有多少个模块以及这些模块的层次和联系,使用架构图, 类似tira-im的第一幅图
  • 总结:
    • 首先架构图(实际上也是一个流程图)确定服务的架构
    • 然后时序图设计请求的大致流程和涉及服务
    • 最后流程图设计接口的实现具体逻辑