如何写好一个技术方案文档(转)
🔑

如何写好一个技术方案文档(转)

Jun 11, 2024
这篇文章教大家如何写好一个技术方案文档,转自twitter宝玉老师。

技术文档的重要性

  1. 帮助你自己想清楚要如何实现你的代码
    1. 如果上手就写代码,多半要边写边想,写的时候才发现很多细节没考虑周全,如果先写文档,在写文档的过程中就能把很多问题想清楚。
  1. 让其他人理解你的想法,从而能给到你有价值的反馈
    1. 如果我们在写代码时,就可以了解最佳实践,可以借鉴其他人的经验教训,那么可以少走很多弯路。但是要让别人能给你提出有价值的反馈,前提就是要让别人理解你的想法,让别人了解你的想法,最好就是用文档描述出来。
  1. 修改文档的成本要远低于修改代码的成本
    1. 我在Review代码时经常遇到代码思路不对或者完全错误的情况,这种时候很难沟通,对方也容易有情绪,觉得是在否定他的工作!另外修改代码的成本是真的很高,尤其是交付日期将至的情况,最后只好凑合着先上去,想着以后再改,但通常以后再不会改!
  1. 作为以后维护的重要参考
    1. 一个长期维护的项目,人员流动是避免不了的,如果没有文档,新人加入后很难了解整个系统,如果有好的设计文档,那么就很容易从整体上了解系统架构,维护起来也会容易很多。

模块划分

一、需求说明

做系统设计,一定是为了解决问题的,可能是为了实现一个功能,可能是为了提升性能,可能是为了重构代码,但是如果目的不明确,或者方向错了,那么后面再好再优秀的设计也会南辕北辙,越做越错。
所以写系统设计文档,第一件事就是交代清楚你的需求是什么,哪怕有需求文档,也应该把关键的内容摘录出来。
在需求中,一般会分两类需求:功能性需求(Functional Requirements)和非功能性需求(Non-Functional Requirements)
简单来说,功能性需求就是偏产品的,必要性的需求,比如说要做一个用户登录的功能,用户输入正确用户名密码可以登录,错误的用户名密码要提示错误信息。
而非功能性需求就是偏技术的,并非是必须的,像安全性、可用性、可靠性等要求,比如说用户登录要防止Sql注入,要能承载1W用户同时登录。
这两部分最好分开,尤其是非功能性需求,在设计时很容易漏掉,但实际上非常重要,对后续的系统设计也有一定影响。
notion image

二、设计范围(Scopes)

有时候我们在做系统设计时,觉得无从下手,一个原因就是因为想太多,觉得要做一个牛逼的设计,未来五年十年都不用变的那种。
所以给自己的设计加上范围和边界非常重要,这样你在设计时就知道边界在哪,而不是无限的扩大你的范围。同样在做设计审查时,和其他人讨论时,如果大家都明白范围和边界,那么讨论起来也更容易达成共识。
notion image

三、技术选型

在很多时候,我们都需要对技术进行选型,尤其是前端,框架太多,选React还是Vue?选Redux还是React Context?选JavaScript还是TypeScript?
很多时候选择什么技术并没有绝对的优劣,但不同的技术选型对系统设计影响很大,所以技术选型有必要在文档中有体现,说明为什么选择某种技术。
技术选型本质就是在做技术决策,做决策本质就是做取舍权衡(Tradeoff),Tradeoff就要把每一个Tradeoff对应的:成本(Cost)、收益(Benefits)和风险(Risk)列清楚。这样在和其他人讨论时才有充分的依据。
有必要的话,技术选型会议可能要先开,先确定技术选型再做后续设计,因为技术选型会对后续系统设计有影响。
notion image

四、概要设计(High-level design)

做系统设计,顺序很重要,先整体再全局,如果一开始就在纠结各种细节,那么会越想越复杂,最终陷入其中难以自拔!
概要设计主要从两个方面(不限于):
  1. 服务架构。有多少服务?各个服务之间是什么关系?
  1. 模块架构。有多少模块?分多少层?模块之间的关系如何?
概要设计其实不复杂,花几张框线图就可以描述清楚模块和模块之间的关系。
notion image

五、详细设计

在前面的铺垫都完成后,就可以做详细设计了。详细设计并非说一定要多精细,我以前听说日本外包连类和方法都设计出来了,只要找外包把具体方法实现就好了。但我觉得没必要到那个程度,只要把一些关键点描述清楚即可。
至于详细设计到什么度的原则:我觉得核心在于涉及模块、系统之间交互的细节一定要描述清楚,比如说API Schema、数据结构、存储结构等。这样在分工协作的时候,才会比较容易协作。
以我们团队前端的系统设计为例,我对我的团队的设计文档要求体现以下内容:
  1. API协议(API Schema)
如果涉及前后端的交互,API的协议是什么?REST还是GraphQL?传入参数是什么?输出的结果是什么?各种错误码是什么?
notion image
  1. 数据模型(Data models)
比如你要在前端后端之间传输数据,各个数据实体的结构是怎么样的?数据实体的关系是怎么样的?这个一定要描述清楚,这样前后端可以更好协作,另外好的数据结构能带来更好的性能。
notion image
  1. 数据存储结构
即使是前端项目,也涉及存储,比如有的数据适合存Cookie,有的适合存Local Storage,还有其他的像服务端Session、本地Session Storage、本地数据库等等,各有各的优缺点,需要根据使用场景灵活选择,并且要设计好存储的结构,考虑好数据更新和缓存失效的问题。
notion image
  1. 组件结构
作为前端项目,尤其是React这种,所有的UI都是由各种组件搭建起来的,但是当UI复杂的时候,怎么样组织、重用你的组件很考验设计,所以在系统设计文档中,要体现出你组件结构,以及组件和数据之间的关系
notion image
  1. 状态管理 在现代前端框架中,UI和状态是分离的,状态管理必不可少,各种UI事件下要触发什么样的action,每个action导致什么样的数据变化,这些数据流需要描述清楚,最好能结合组件一起将整个状态的变化描述清楚。
基本上在详细设计中把这些问题讲清楚,就差不多可以了。
notion image
对于系统设计文档,以上就是所需要的关键部分,简单再总结一下: 一、需求。你要解决什么问题? 二、范围。你的边界在哪里? 三、技术选型。你的决策依据是什么?成本、收益、风险是什么? 四、概要设计。从整体来看你的架构是什么样的? 五、详细设计。从局部来看你的架构是什么样的?
 

其他小细节

  1. 多画图少写字,一图胜千言。http://excalidraw.com
  1. 复杂的文档要分多次确认,先粗再细,先写简单的slides和关键的团队成员确认清楚大方向,然后再用Google Docs这样的在线文档写详细的文档。
  1. 尽量用在线协作文档,例如Google Docs、石墨文档,这样其他人可以方便评论和帮忙编辑,也好维护版本
  1. 将团队的设计文档集中存放,不要因为团队成员离职就不能访问了(这事我们遇到过)