

👉目录
0 前言
1 宏观
2 中观
3 微观
4 补充
俗话说,一图胜千言。日常工作中,当我们要表达自己的设计思路的时候,会画各式各样的图。但因为各自知识储备的差异,思维的差异,不同类型的系统侧重的架构设计点也不一样(C端高并发系统、B端复杂业务系统、大数据离线系统、流式计算系统、机器学习系统、客户端系统),导致在日常方案表达与沟通中,所画出来的图"五花八门",没有一个相对标准化、通用的"技术方案沟通语言",这给沟通带来歧义,同时也不利于个人的思维提升,不能形成一个体系化的思考方法。
本文综合了自己多年的架构设计实践和业界众多的软件工程方法论,总结出一个相对通用的"技术方案沟通语言"。思维即语言,语言即思维,一切不能用"语言"表达的思维,只能说明没思维。 更详细介绍,还可以参见作者出版的书籍《软件架构设计:大型网站技术架构与业务架构融合之道》
关注腾讯云开发者,一手技术干货提前解锁👇
00
前言
(1)不同的系统,复杂性往往体现在不同方面,画图的侧重点不一样,需要画的是体现复杂性的那一面。
(2)本方法论考虑了方法论的投入与回报是否匹配问题,糅合了软件4+1视图、领域建模 (DDD)、 微服务拆分、UML、ER图等几个方法论。
|-----------------|-------------------------------------------------------------------------------------|
| 系统的类型 | 侧重点 |
| 1. C端大流量、高并发系统 | 系统架构、高并发、高可用等 |
| 2. B端复杂业务系统 | 领域建模、数据建模、微服务拆分。这里面又分为了2类:类型1: 自身逻辑不复杂,但上下游的系统特别多、链条长; 类型2: 上下游少(处在链条末端),但自身逻辑非常复杂; |
| 3. 基于大数据的各种业务系统 | 海量数据的处理问题(存储、转换、数据一致性保证) |
| 4. 数据分析、算法模型类系统 | 数据驱动的思路、模型、算法 |
下面的方法论,比较适合上面的前2类系统,第3类、第4类只在宏观图的画法上有一点适合。
01
宏观
1.1 上下文图
此图目的:
让别人明白你的系统的背景(业务背景、系统背景)。
思考方式:
把你的系统当做黑盒,描述2件事情:
-
你的系统为谁服务? (这个"谁",可以是某个用户,某个角色,也可以是某个系统) - - 你到哪去???
-
你的系统依赖谁? - - 你从哪来??
业界参考:
C4模型官网:https://c4model.com/
是否必选:
上下文很简单的情况下,此图可以和下面的"系统架构图"合并成一个。
1.2 系统架构图
此图目的:
(1)明确每个系统的定位与职责边界,明白某个系统在整个体系中的"位置"在哪。
(2)明白跨团队的各个系统,或者一个大系统的几个子系统之间,是怎么串联起来的。
思考方式:
(1)概要性的描述跨团队的多个大系统之间的核心交互
(2)概要性的描述一个团队的一个大系统内的多个子系统之间的核心交互。这2点糅合在一个图上展示出来。
备注:这里说的系统/子系统,在物理上对应了一个集群(一个微服务的集群,或者一个独立部署的系统)。
如果只是一个逻辑模块,和其他代码块,部署在同一个进程里面的,不能算是一个"系统",最好不要出现在此图中。
是否必选:
简单的系统,比如就1个单一的微服务,或者单体应用( UI+ 逻辑层 + DB),和外界其他系统没有交互,此图可以不画。
1.3 物理部署
目的:
有了物理部署,才能和上面的系统架构图对应起来,让人明白,上面的每个方块,是一个集群,还是单机版的进程?
是单机版,是否存在高可用问题?
如果是集群,是不是多个系统,部署在同一批机器上?
画法:
物理部署不一定需要图,可以是一个表格,对上面的系统架构图,进行补充。类似如下:
|----------|----|--------|-------------------------|----|
| 系统 /子系统 | 机房 | 机器数 | 对外提供的网络协议:http/tcp/udp? | 备注 |
| Java微服务1 | xx | 2台 | http | |
| 子系统2 | xx | 1(单机版) | udp | |
| ... | | | | |
02
中观
2.1 是否要严格区分领域模型、数据模型(ER图或者类图)?
领域模型: DDD 、UML的思想,领域模型通常用UML来画。
数据模型: ER图,大家经常画。
个人看法:严格区分这2者,实施起来往往非常难。如果2者不一致,不如不画。
1、领域模型,大家不知道怎么画
2、领域模型到数据模型,如何映射、转换,太随意。虽然有教科书教大家转换,但基本没人学。
实体:表 = 1 :1的时候,领域模型映射到数据模型没有歧义,但有很多例外情况:
(1)领域模型中的抽象/继承,父类/子类,在ER中没有体现
(2)领域实体之间的N:N关系,ER中需要中间表
(3)多个实体对应1张表
(4)视图如何体现? 视图指一种UI呈现,没有数据存储,多个数据表的数据按某种规则聚合成一个视图
(5)领域模型中的策略、规则类的实体,最终映射到一段代码逻辑,而不是表
所以结论是没有严格区分领域模型,还是数据模型,主要以数据模型为主。
目的:
程序 = 数据结构 + 算法,软件工程 = 领域模型/数据模型 + 功能逻辑。
"数据结构"(这里指广义的数据结构,不是大学教科书上的数据结构),是任何一个软件的基石,其重要性怎么强调都不过分,系统的性能、复用性、扩展性、维护性、数据一致性等,往往都和"数据结构"密切相关。
对于严格遵循DDD的软件开发,会区分领域模型和数据模型。但目前大部分实践场景,并没有对2者做严格区分。不管是领域模型,还是数据模型;不管是DB存储、还是KV缓存/KV存储、内存存储,都会有一些共性的问题需要回答:
(1)你的系统有哪些关键的"实体"?
(2)这些实体之间的关系,是1:1, 1:N, N:1, N:N? 最终组成的这个网状关系是什么样的?
重点:
(1)ER图和下面的3.2章节的表设计的区别是:3.2章节事无巨细的列每个字段的详细解释。这里ER图是省略了大部分字段,只描述每个表的业务主键、外键、关键state,以及表与表之间的关联关系。
(2)如果数据是存在KV存储/KV缓存,同样需要数据模型。因为kv里面的多个kv之间,可能有复杂的关联关系。
如果部分数据在KV,部分数据在DB,更需要去很好的描述2者的关联关系。这还涉及到2边的数据一致性问题。
2.2 时序图
这个日常画的最多,但也存在问题:
泳道中的每1列,是一个跨团队的其他人的系统,还是自己系统内部的一个子系统,还是一个逻辑模块,还是一个用户?
尽可能在同一个层次上描述问题。
画法:
直接参考UML。
2.3 状态图
对于有复杂的状态流转的系统(对应DB中某个state字段),此图一定要画。
画法:
直接参考UML。
2.4 并发运行视图
思考方式:
架构4+1理论中,有一个视图就是"运行视图"。主要描述单机的多线程/多进程之间如何通信、如何同步问题。
是否必须:
对于标准化的Java微服务,其微服务框架内部的多进程/多线程模型是固定的,上层开发人员只需要写业务代码。
对于这种情况,不需要去写并发运行视图,因为是标准化的,大家都一样!
对于C++里面常见的自己从网络框架层一直写到业务层的系统,这个需要重点描述。没有这个图,没办法表达锁、阻塞与唤醒、线程安全等各种并发问题。
在一个进程内部(RiskServer进程)内部的多线程模型,不要把多进程和多线程画一个图上,除非图标上有明确区分是1个进程,还是线程。
2.5 数据流程图(离线大数据处理系统)
对于离线数据处理系统,数据链路可能很长,整个过程可能涉及到tdw/hdfs, hbase,络子任务,java/c++处理,mysql,UI界面。。。
对于这类系统,数据流程图非常关键。
03
微观
这个大家已经很熟悉,不再展开。
接口文档;
表设计(字段详细解释);
(1)自己的表,在哪个实例,哪个DB上面?
(2)每个表的字段解释。
后台任务;
(1)你的系统有多少个后台任务,调度周期多少?
(2)单机版,还是分布式调度?实现方式:crontab, quartz, XXL-job,还是其他什么框架?
(3)后台任务,跟服务,是部署在同一台机器上面,还是不同?
04
补充
一个标准化的技术体系会极大的降低文档编写复杂度、降低团队沟通难度:
当我说"接口"的时候,默认是某种标准化的RPC;
当我说"后台任务"的时候,默认是某种标准化的分布式调度上面的一个任务;
当我说"消息"的时候,默认来自某种标准化的消息中间件;
当我说"DB"的时候,默认来自某种标准化的DB部署;
...
这一系列的"默认",其产生的效率提升往往会超出预期。
-End-
原创作者|余春龙
感谢你读到这里,不如关注一下?👇

📢📢来领开发者专属福利!点击下方图片直达👇


你在架构设计中用过哪些好用的工具或方法?欢迎评论留言补充。我们将选取1则优质的评论,送出腾讯云定制文件袋套装1个(见下图)。6月18日中午12点开奖。





