一个靠谱的技术方案文档是怎样的
对所做的事情的理解越深,就能做的越好。
缘由
技术方案文档的主要作用是:
-
指导实际开发,减少开发过程中踩坑甚至返工;
-
便于交流和探讨。
大多数程序员都会写一个基本的技术方案文档,但不同的人采取的要求不一样,语言组织能力的不一样,就导致了:不同的人写出的技术方案文档,有的看起来非常详细,大量细节掺杂其中,可能会因为重点不得当导致该突出的东西没有突出,有的看起来则比较简陋,难以起到技术方案指导和交流的作用。
那么,一个靠谱的技术方案文档,究竟应当包含哪些要素?
理解与表达
在文章 “编程巨星的唯一秘诀” 里有句话说得很好: 对所做的事情的理解越深,你就会做的越好。
对于作为知识工作者工种之一的程序员来说,我们所做事情能够抵达的程度和境界,取决于我们对事物的理解程度。而技术方案文档,正是最适合用来表达我们所思所想的载体。
这里所说的“对事物的理解程度”,绝不局限于技术层面,而是可以扩展到业务、产品、客户、领域、商业、心理学甚至是政治、经济、文化等多个层面。
当进行技术方案交流时,会出现两种情况:
-
如果别人提出了方案里没有说到的点,有思考过,但没有表达出来,是表达力的问题,需要提升表达力;
-
如果别人提出了方案里没有说到的点,没有思考过,那说明是理解还不到位,需要再反复推敲,提升对事物本质的理解能力。
理解的程度是有区别的。 比如说一个大数据量问题要加缓存。 大数据量有多少,什么情况下存在峰值,为什么会存在峰值,为什么要加缓存,要加多少缓存, 缓存的 key 如何组成及为什么,缓存的过期时间怎么设置及论据是什么,缓存失效会导致什么及如何处理,系统崩溃导致的缓存丢失怎么处理。问题提得越多,且能够回答得更加详细,说明对问题的理解也更透彻。
始终要用高标准去要求自己,不然就很容易原地踏步,只是完成了开发任务,能力却得不到提升和质的飞跃。
接下来,谈谈技术方案文档的若干要素。
技术方案文档要素
问题与背景
问题定义正确清晰,是解决问题的成功的一半。 但很多程序员往往对这个部分容易忽视,三言两语,或者直接引用一个有很多文档的文档集合。这些做法都不够好。
合适的做法是: 围绕自己要解决的问题(比如新增需求、功能增强、性能优化、可扩展性设计、高可用设计),根据自己对现有系统设计及实现的理解,画一张图,把现有逻辑流程画出来,标识出哪些地方存在什么问题,需要做什么样的改进。
产出
- 通过一张图以及一段文字,就能把问题说清楚。
如果不能做到这一点,那就返回去再思考再表达,直到能做到为止。
把现有设计及实现流程画出来,也不需要做到很细节的程度,通常只要包含如下元素:
- 查表:单个还是批量,表的数据量量级,表的索引,重要的查询语句;
- API 调用:一次请求中的 API 平均调用耗时、最大耗时; API 调用数量及次数;
- 关键点: 比如性能优化,就是热点区域的逻辑及耗时。
强调的是子系统之间的交互及问题的核心点,而不是具体的代码逻辑细节(除非很重要,影响全局质量)。
技术目标
要达到的技术目标是什么,产生的业务价值是什么。要有明确强烈的目标感,才能作出正确更好的设计。
有必要的话,可以附上产品目标。如前所述,对一件事情的理解越深(尤其是前导性的目标), 最终就能走得更远。
产出
- 逻辑:清晰、易维护;
- 性能:可接受的 TPS,QPS,RT;
- 大数据量:能够处理的数据量大小;
- 扩展性: 要支持新的业务,开发量如何;
- 可伸缩性: 能够支持动态扩容;
名词解释
名词解释往往反映了这个问题域里最重要的领域概念。
对名词有一个精确的定义,能够在很大程度上避免混淆,在方案的探讨交流上做到同频思考,也考察了一个人对这个问题域里最基本概念及关联的理解。往往对于一个事情的视角不同,有可能导致最终设计出来的东西和业务适配能力会有很大差别。比如,告警究竟是针对对象,还是针对行为。从直观来看,告警似乎针对的是行为,但如果只禁行为不禁对象,就无法封堵源头。因为风险源头是恶意对象产生的。行为只是结果。比如一个程序连接一次恶意IP,封堵了这次行为,这个程序还会继续连接恶意 IP。就会治标不治本。
要注意,这里的“名词解释”指的是领域概念,而不是技术手段。比如访问关系业务里,访问关系就是一个很重要的领域概念,它包括访问者/被访问者、访问协议、访问的方向。而用于实现大数据量处理的技术手段中的 MD5 就不是领域概念,而是技术概念。再比如,资产清点,资产就是一个很重要的领域概念, 它包括主机、容器、镜像、仓库、Pod、Service、Endpoint、进程、端口、web 服务等所有跟安全相关的物理或虚拟实体,而实现资产清点相关的事件 handler 就不是领域概念。
产出
- 问题领域里的概念对应的名词及精确定义。
业界做法
这部分至少要有一点产出,否则,说明对业界方案缺乏了解,只顾自己造车。
产出
- 业界的基本解决方案及各自的利弊。
总体思路
定义清楚问题、背景和目标后,就需要给出总体解决思路。
产出
- 通常也是若干张图,辅以说明文字;
- 基本的存储与流程、处理逻辑。
总体思路不需要很详细。对于图中容易让人产生疑问的地方,主动说明其含义。 大多数程序员是能够做到这一点的。 但不能止步与此。很多不能成为技术方案,是因为只是一个总体思路。但要起到交流探讨的作用(到能够开会议的程度),就非得自己先把方方面面想清楚。
详细设计
至少给出两种解决方案(哪怕其中一种是蛮力法)。 对于最优选项和一般选项,最优选项可以写得详细些,一般选项可以写得简略些,但不可以不提。
产出
- 至少两种方案;
- 每一种方案的具体做法,利弊、支撑的论据、考量的因素、如何支持技术目标;
- 存储设计(表、字段、索引、分库分表分片)、流程图、处理逻辑。
方案决策
当作出方案决策时,决策内容是什么,最主要的考量因素有哪些,为什么是这些因素,是由什么决定的?
产出
- 技术决策内容
- 作出技术决策的最主要的考量因素
- 考量因素的缘由:产品需求、扩展性、业务核心价值等。
依赖变更处理
模块之间往往有依赖关系。基础业务模块依赖基础模块,具体业务模块依赖基础业务模块,具体的业务模块之间也有依赖关系。
比如业务组是一个基础模块,资产清点是一个基础业务模块,而访问关系、容器行为白名单、微隔离模块则依赖于资产模块。
设计方案一定要考虑依赖变更的处理,尤其是对于基础业务模块变更的情形。如果未能考虑到,很可能会导致设计方案存在重大缺陷。
产出
- 依赖的基础模块、基础业务模块、具体业务模块;
- 受影响的变更,处理逻辑。
场景走查
场景走查是技术方案文档的“最后一英里”,也是容易被忽略的。 很多人写出技术方案后,就觉得这个方案绝对没问题了,这是一种经验主义的做法,虽然有些效率,但并不总是可靠。实际上,是可以通过场景走查来做一番推敲的。如果对于已知的各种场景,技术方案都能支撑,那就说明技术方案是真的经得起推敲,而不是从感觉和经验上觉得可行。
产出
-
业务场景及用例
-
对于每一种场景及用例,流程图和数据存储示例
参考资料
列一些参考资料,说明在这个技术方案上参考已有成果的程度。参考资料也便于文档的读者拓展理解这个问题域的更多信息,或许他们能提出更好的建议呢。
产出
- 参考书籍
- 参考论文、博文
- 引用出处
借鉴学习
要写好技术方案文档,还需要多多看一些优秀的技术方案文档。
榜样的力量是有力的。人类具有本能的模仿学习能力,哪怕只是模仿优秀做法,也能让自己有很多提升。
小结
简而言之,一个靠谱的技术方案文档就是: 针对一个具体的需求或优化,所涉及的问题背景及业务价值、技术目标、领域概念及精确定义、总体思路、现有方案的做法及利弊、新方案的利弊分析、最终方案决策/考量因素/论据支撑,无论大点小点,都写得明明白白清清楚楚,重点和核心点做了充分的讨论,非重点和非核心点让人觉得自己想的都提到了。