不会画图? 17 张图教你写好技术文档

横看成岭侧成峰,远近高低各不同。为了更好地理解软件系统,我们需要借助于多种图表工具,从不同的视角出发,全方位的理解系统设计。以便在设计阶段足够充分预估系统瓶颈,实施难度,开发工时等,在业务功能上实现良好扩展性,性能上高可靠,高可用。达到数据绝对安全,性能足够优异。支撑业务需求快速迭代。

软件系统可以按如下分层

  1. Iass: 基础设施软件,包括操作系统(网络,存储,计算),虚拟机,Docker等基础软件。
  2. Paas 平台即服务: 包括我们日常的消息,缓存,数据库,等中间件。也应该包括框架和 类库。例如ioc,orm,rpc框架; 图片,特殊文件处理的第三方类库等
  3. Saas 软件即服务: 我们日常的一些应用,无论是2B,2C都属于此。

以下我们将重点分析借助哪些图表工具 可以分析 应用软件系统(Saas层)。这些图表的阅读者 应该是开发者,产品经理,业务架构师,系统架构师,技术管理者等。

用例图

用例图是最清晰,最容易理解的图表,用例图从用户角度出发

要素

  1. 如何使用我们的系统。如果系统已经完成,可以使用简洁版本的 用户使用手册代替。
  2. 有哪几种使用流程,哪些应用场景。
  3. 每种流程需要做哪些事情。

用例图首先需要分析系统有哪些使用人员,可以借助以下问题分析

  • 谁将使用该系统的主要功能。
  • 谁 将需要该系统的支持以完成其工作。
  • 谁将需要维护、管理该系统,以及保持该系统处于工作状态。

例如简单的用户修改资料

用例图因为其简单直白,容易被系统设计者忽略,实际上 对于一个完全未接触系统的人,用例图是最友好,最直白的,可以让小白 快速的了解我们的系统 给哪些人提供了哪些功能。功能之间的联系是什么

用例规约

用例规约是对用例的详细描述,一般包括简要说明、主事件流、备选事件流、前置条件、后置条件和优先级等

用例规约既关注主事件流所描述的成功场景,也关注备选事件流所描述的异常场景,有利于促进系统化思维、发现异常场景、完善系统功能和提高易用性;

后置条件应覆盖所有可能的用例结束后的状态。即后置条件不仅仅是用例成功结束后的状态,还应该包含用例因发生错误而结束后的状态

示例

一般情况可以只描述重要需求,关键用例的用例规约。一般需求可以忽略。(PRD里绝对不能忽略)

用例图和系统页面 如果有 更详细的使用手册,则可以更快速的全面理解系统的功能。例如展示一下我们的系统页面。更加直观和清晰。

只有更好的了解系统提供了哪些功能,有哪几种角色,才能理解 系统为什么这么设计? 某些人之所以会觉得用例图多此一举, 是因为其对系统本身足够了解。但是他们忽略其他人对系统还是完全一片陌生。需要借助用例图,最直白的了解系统

数据模型图

程序=数据结构+算法,软件程序就是对输入数据进行处理,按照一定的算法,输出特定的数据。 数据是程序的核心,也是容易变化的部分,例如最常见的变化: 需要增减字段。

此时需要对数据进行建模,梳理模型之间的关联关系,为的是把关系最紧密的数据 放到一个模型里,独立扩展。 数据模型图描述了 模型之间的关联关系,每个模型有哪些字段 。 三要素 ● 模型 ● 属性 ● 模型间关联关系

数据模型图包括 E-R图,数据库实体图。等。

  • E-R图使用中文,不涉及表结构,更简单。
  • 数据库模型层: 描述数据库层面的关联关系和表设计, 虽然比ER图更复杂, 但是更全面,适用人群都可以看懂。
  • 大多数情况下 我们的设计文档是给产品和研发,技术管理者看的。使用数据库实体图也可以看懂。(看不懂的让他去学)

个人认为设计文档里可以忽略E-R图,直接上数据库实体图。但是这就要求数据库实体图 有充分的文字说明,例如属性注释,关联关系说明等。

E-R 图示例

数据库实体图(数据库 ER 图)

数据库 ER 图的梳理过程

数据库 ER 图,实体图或者 领域模型图的设计非常考验设计经验。需要领域专家根据用例图,用例流程图,反复的需求沟通。不断地推敲以下问题

  1. 业务的扩展点,变化方向 在哪里,未来计划的演进方向。
  2. 系统的扩展方向是哪里?如何实现扩展性
  3. 应该包括哪几个 领域实体。
  4. 领域模型的边界 应该在哪里。关联关系是 1V1,还是 1对 N 等等。

数据库 ER 图的分析过程 可以使用 DDD 等设计方法 。

流程图

系统设计阶段 只需要覆盖核心和关键的业务流程即可。对于细枝末节的一些简单流程应该忽略。 (有精力和时间可以覆盖非核心流程)

管理流程和 用户流程

以营销系统为例,分为管理流程 和用户流程

  • 运营创建了一个营销活动。这个过程是管理流程。这个流程对于性能的要求不高。流量入口不同。
  • 用户下单等行为, 触发了某些营销活动,这个流程对于性能要求,安全性要求就很高。

不同流程的关注点不同。例如dubbo的rpc系统,也可以分为 初始化流程 和 方法调用流程

  • rpc provider 接口提供者需要初始化时注册接口。rpc consumer需要在初始化时监听接口。
  • rpc调用流程 从consumer端到provider 是调用流程。

流程图画法

流程图的画法比较灵活。以下是个人经验和习惯

  • 组件思维: 可以描述 组件之间的控制流调用
  • 数据思维: 可以描述数据之间的数据流变化。

一般使用方框表示 组件,连线 表示调用方法,动作 或者数据。

组件思维

按照组件思维 设计流程图。要求把系统的组件先抽象出来,每个组件处理哪个步骤。淡化了输入输出, 是简化版的 调用时序图。(时序图描述方法调用层次,更加细化和清晰。)

以下示例是dubbo Provider端 暴露一个服务的 组件调用的控制流变化图

数据思维

按照数据流程图描述,组件之间传递的是 数据,数据流描述了 一个组件或系统的输入 和输出 是什么。 其实大多数业务系统,使用数据流程图不太好划分,因为 一个业务流程内主要是针对两三个模型进行处理。组件之间的输入输出界限并不明显 为此可以 将数据流程图和控制图 合二为一。 方框依然表示 组件,但是连线可以同时包括动作和数据

流程图中的非功能型设计

高可靠 高可用 性能瓶颈,流程图中可以介绍核心读写流程的高可用,高可靠设计; 即数据可靠性如何保证,系统可用性如何保证。性能瓶颈在流程中哪个节点。如何优化等

以下仅供参考

  1. 数据存在哪里,同步/异步写入,异步写入的一致性保证
  2. 并发操作如何保证一致性(例如库存?)
  3. 高并发场景如何提高系统可用性,读流程如何优化,写流程如何优化
  4. 是否 Stand-by 设计双活。
  5. 幂等性,重试策略、负载均衡策略

时序图

时序图 是更加详细的系统流程图,一般的系统流程图覆盖了关键的系统组件,关键的数据处理节点,但不会具体到哪一个类,哪一个方法。 时序图要求关注 程序执行时的 控制流,时序的展示更好像是 系统执行时的 方法调用堆栈。

时序图要素

  1. 方法调用堆栈(核心)
  2. 分支和循环描述,
  3. 方法和入参描述
  4. 主要的一些关键节点注释

时序图示例

可以看到时序图 精确到 某个类 调用了某个类的某个方法,把方法的调用嵌套的深度 和层次 都能展现出来。 配合 重要的 关键节点注释,可以让读者即使不读代码也可以看到整体的方法调用体系。 通过时序图我们可以得到

  1. 某个类在时序图的哪个位置,负责的工作是什么
  2. 在当前流程中,某个类上下游的依赖是什么

类图

类图描述了类和类之间的依赖关系(组合,继承,接口)

类图要素

  1. 继承、实现、组合关联关系
  2. 类的关键核心方法。(记得加注释,用以描述本类扩展了哪些能力)

下面拿一个Spring ioc容器的类图

类图的箭头关系 描述了 两个类之间是否依赖,集成/组合/接口实现。

什么时候使用类图?

简单地业务流程不需要类图

例如一个接口只有一个实现类,没有复杂继承关系 基本上不用写类图。

复杂的继承体系需要类图

类似于 Spring 等极为复杂的框架,为了实现最大程度的复用和可扩展性。使用了大量的继承、接口实现类 提高高扩展性和可复用性。这个时候如果没有类图,根本无法全面的了解 一个接口,一个类的继承体系。不清楚某个类在继承体系中的位置。

为什么类图不可以归到 流程图里

一般情况下只有流程图和时序图里面能具体精确到某个类。当读者在流程图、时序图里经常看到某个几个类,就会疑问,这几个类有什么关联关系呢?

此时 可以择机是否需要 梳理一个 类图展示依赖关系。

类图和设计模式

设计模式的具体介绍都会使用类图展示。例如工厂模式 的类图

系统架构图

系统架构图为了描述应用内部的组件,模块等。一般情况下分为 全系统架构图,单应用架构图

全系统架构图

业务架构图是从业务逻辑的视角出发,整齐地展现出一个企业各类系统之间的层次和关系

单应用架构图

单应用业务架构图按照层次结构可以分为经典的三层结构:展现层、业务逻辑层和数据层

应用架构图

应用架构图的关注点是 应用 在整个系统的位置。(和上面的全系统 业务架构图类似)。应用架构需要把应用在整个系统的位置描述出来。

以下为优惠券系统的 应用架构图。基本描述了一个应用服务在整个优惠券相关微服务里 所处于的位置

例如 CouponJob服务 负责发券,上层会有各种形式的发券活动关联该服务。兑换码,领券页面领券等等都依赖CouponJob发券服务能力。

应用间依赖关系 最理想的情况是单方向依赖,如果上下游的两个服务存在明显的 循环依赖,此时需要考虑,两个系统是否耦合严重, 两个系统是否实现了类似的功能呢? 是否需要合并为一个服务呢?

是否可以把关联性很强的业务模块放到一个服务里比较合适呢?

应用架构重在描述应用之间的依赖关系,以及应用所处在系统的位置。是上层应用还是底层应用? 设计应用架构图时 不建议把 应用内的模块划分也囊括在应用架构图中,这样会导致架构图过于庞大,不利于理解

一个架构图只需要描述清楚 一个视图即可。(职责尽量单一)

以下为HBase的应用架构图

可以从表中看到

  • Zookeeper负责存活性监测等集群管理任务。
  • master不负责数据读写,只负责DDL建表等语句,负责RegionServer故障转移流程
  • RegionServer负责接收客户端读写数据
  • HDFS 作为分布式存储,接收RS读写 (至于RegionServer内部有哪些模块,如何读写 自然借助于其他架构图。每种架构图只是从一个视角描述 系统)

部署架构图

部署架构图重在描述应用在线上部署的情况

部署架构图核心关注点

  • 流量从管理端还是用户端过来
    • 是否做了鉴权
  • 流量从哪几个 nginx 过来,公网还是内网,域名是哪个(公网内网,域名不同)
  • 应用是否做了负载均衡,策略是什么
  • 是否多机房部署,应用部署在了哪几个机房。
    • 机房之间的流量如何路由的; 是否存在跨机房调用
    • 是否按照用户维度进行了 Set化
    • 是否按照地区维度进行了机房路由
    • rpc调用路由规则是什么,在哪里管理路由规则
  • 部署机房 是虚拟机,物理机,还是 Docker。 私有云,公有云,还是混合云架构
  • 依赖的数据库和应用是否同机房部署?
  • 其他MQ,Redis,Es等中间件 机房部署在哪里。是否跨机房等。

以下部署架构描述了 应用在容器上部署,用户请求经过 SLB 负载均衡。静态资源访问,数据库服务部署在RDS。

全链路调用 结构图

以下场景需要梳理全链路上下游依赖图

  1. 接口参数需要变更,接口实现需要变更。确认不影响上游(一般具体实现细节对上游屏蔽。)
  2. 下掉接口、迁移到新接口
  3. 限流,熔断,降级策略需要通知到上游

当出现以上内容时,我们需要感知到哪些上游依赖了我们,在什么业务场景下依赖,重要性,优先级如何统一的梳理出系统 rpc 接口,http接口,mq消费者,共享数据库,等 上下游依赖。 可以以表格的形式,例如 对于项目内部的方法调用,模块依赖,我们可以快速的梳理清楚上游的依赖。例如使用IDE 的快捷键。但是微服务下,需要获取调用链路图,只能依赖于 服务治理框架和代码扫描工具 提供的能力,梳理每一个接口上游的依赖。

梳理后可能发现需要 对接口进行鉴权,防止任意调用方可以调用我们的服务。至少可以让我们感知到接口被调用,防止大流量,不合理的业务场景 进行调用。也方便我们日后升级。

每一种架构图都是一个独特的视角

架构图的视角

  • 用例图: 用户,产品经理,测试人员 可以直观,清晰的了解我们的系统使用场景,能做什么?
  • 数据库实体图: 业务架构师,业务专家,产品经理 更清晰了解 建模的过程,是否存在领域划分不清晰,领域耦合问题
  • 流程图: 给开发工程师,业务架构师,业务专家 更清晰的 了解 核心流程 ,数据如何在组件之间流转的,各组件如何调用的
  • 系统架构图: 开发工程师 可以借助于此快速了解 系统内 共哪几个模块,如何进行分层的。各层职责。
  • 应用架构图: 业务架构师可以看到 微服务之间是否存在耦合,是否依赖不合理,界限是否清晰。开发工程师可以了解负责的系统处于 总体架构的哪个位置。
  • 应用部署架构: 业务架构师,开发工程师 ,以及运维工程师 更清晰的了解 服务部署环境, 流量入口,负载均衡策略,路由策略,中间件部署情况等

以上我们分析了设计文档应该包括哪些具体的 图表,此外

设计文档基本原则

设计文档的编写 应该遵循以下基本原则

  1. 文档是给人看的。 要给目标读者 讲的足够透彻,每个读者的视角都要考虑到
  2. 可落地。要求文档具备足够的设计细节,能准确预判技术难点,对于技术难点提出明确的解决方案(要覆盖关键需求和流程)
  3. 一个架构图只需要描述清楚 一个视图即可。追求大而全的架构图只会让人看不懂,自己也无法再修改。(职责尽量单一)
相关推荐
AskHarries23 分钟前
Java字节码增强库ByteBuddy
java·后端
佳佳_37 分钟前
Spring Boot 应用启动时打印配置类信息
spring boot·后端
许野平2 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
58沈剑3 小时前
80后聊架构:架构设计中两个重要指标,延时与吞吐量(Latency vs Throughput) | 架构师之路...
架构
BiteCode_咬一口代码3 小时前
信息泄露!默认密码的危害,记一次网络安全研究
后端
齐 飞3 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
LunarCod4 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
码农派大星。4 小时前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man5 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*5 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go