[转]如何才能写出好的软件设计文档?
作为一名软件工程师,我花了很多时间在阅读和撰写设计文档上。在磨砺了数百篇文档之后,我发现,优秀的设计文档与项目的成功之间有着密切的联系。
这篇文章将介绍怎样才能写出一份优秀的设计文档。
为什么要写设计文档?
设计文档也就是技术规范,用于描述你打算如何解决问题。已经有很多文章说明了为什么在开始编码之前要先写设计文档,这里不再赘述,不过我想再补充一句:
设计文档是确保正确完成工作最有用的工具。
设计文档的主要目的是迫使你对设计展开缜密的思考,并收集他人的反馈,以便更好地完成你的工作。人们通常认为,设计文档的目的是让其他人了解某个系统,或者作为参考文档。这些只是设计文档带来的有益的副作用,但绝不是它们的根本目的。
从经验来看,如果你的项目需要一个人月或更长时间,那么就应该编写设计文档。另外,一些小型项目也可以从迷你设计文档中获益。
但不同的工程团队,甚至是同一团队中的工程师,他们编写设计文档的方式存在很大差异。接下来,让我们来谈谈优秀设计文档的内容、风格和流程应该是怎样的。
设计文档应该包含哪些内容?
设计文档描述了问题的解决方案。因为每个问题的性质不一样,所以设计文档的结构也不一样。
下面列出了一个清单,你至少可以考虑在文档中包含这些内容。
标题和人物
设计文档的标题、作者(应该与计划参与项目的人员名单相同)、文档的评审人员(我们将在“流程”部分详细讨论),以及文档的最后更新日期。
摘要
摘要可以帮助公司的每位工程师理解文档的内容,并决定是否需要继续阅读文档的剩余部分。摘要最多可以包含 3 段内容。
背景
描述要解决什么问题、为什么需要这个项目、人们需要哪些知识才可以评估这个项目,以及它与技术战略、产品战略或团队的季度目标之间的关系。
目标和非目标
目标部分应该包括:
- 描述项目对用户的影响——你的用户可能是另一个工程团队或另一个系统。
- 指定如何使用指标来度量项目的成功——如果可以链接到指标仪表盘那就更好了。
非目标也同样重要,用于描述项目不会解决哪些问题,让每个人都达成共识。
里程碑
一系列可衡量的检查点,你的 PM 和上司可以借助它们大致了解项目的每个部分将在什么时间完成。如果项目时间超过 1 个月,我建议你将项目分解为面向用户的里程碑。
在设定里程碑时可以使用日历日期,把延期、假期、会议等因素都考虑进去。例如:
开始日期:2018 年 6 月 7 日
里程碑 1——以暗模式运行新系统 MVP:2018 年 6 月 28 日
里程碑 2——弃用旧系统:2018 年 7 月 4 日
结束日期:在新系统中添加新特性 X、Y、Z:2018 年 7 月 14 日
如果其中一些里程碑的 ETA 发生变化,需要在此处添加 [更新],相关人员可以很容易看到更新的内容。
当前的方案
除了描述当前的实现之外,还应该通过示例来说明用户如何与系统发生交互以及数据是如何流经系统的。
这个时候可以使用用户故事。请记住,你的系统可能拥有不同类型的用户,他们的使用场景也不尽相同。
提议的方案
有人把这部分称为技术架构。这部分也可以通过用户故事来进行具体化,可以包含多个子部分和图表。
先从大处着手,然后填充细节。你要做到即使你在某个荒岛上度假,团队的其他工程师也能按照你的描述来实现解决方案。
其他替代方案
在提出上述解决方案的同时,你还考虑了其他的方案了吗?替代方案的优点和缺点是什么?你是否考虑使用第三方解决方案——或使用开源解决方案——来解决问题,而不是自己构建解决方案?
监控和警报
人们经常把这部分视为马后炮,甚至直接忽略掉。而在发生问题后,他们就手忙脚乱,却不知道该怎么办,也不知道为什么会发生这些问题。
跨团队影响
这样会增加轮班待命和 DevOps 的负担吗?
它的成本是多少?
它会增加系统延迟吗?
它会暴露系统安全漏洞吗?
它会带来哪些负面后果和副作用?
支持团队该如何与客户沟通?
讨论
这部分可以包含任何你不确定的问题、你想让阅读文档的人一起权衡的有争议的决定、对未来工作的建议,等等。
详细的范围和时间表
这一部分的主要阅读对象是参与该项目的工程师、技术主管和经理。因此,这部分放在文档的最后。
从本质上讲,这是项目计划的实施方式和时间细分,可以包含很多内容。
我倾向于将这一部分视为项目任务跟踪器,因此每当范围估计发生变化时,我都会更新它。但这更像是个人偏好。
怎样才能写好文档
在讲完优秀的设计文档应该包含哪些内容之后,现在让我们来谈谈写作风格。
尽可能保持简单
不要把设计文档写成你曾经读过的学术论文。论文是为了给期刊评论家留下深刻印象,而编写设计文档是为了描述你的解决方案,并从其他人那里获得反馈。你可以通过以下方式让文档变得更清晰:
- 用词简单
- 使用短句
- 使用符号列表和编号列表
- 提供具体的示例
添加图表
图表便于对几种选项进行比较,而且通常比文本更容易理解。我经常用 Google Drawing 来创建图表。
请记得在截图下方添加一个指向图表源文件的链接,以便在发生变更时可以更新图表。
包含数字
问题的规模通常决定了解决方案的规模。为了更好地帮助评审人员了解情况,请在文档中使用实际的数字,例如数据库行数、用户错误数、延迟,以及这些数据与使用量之间的关系。(还记得大 O 表示法吗?)
加入趣味性
记住,技术规范不是学术论文。另外,人们喜欢阅读有趣的东西,但也不要为了趣味性而偏离了核心思想。
自审
在将设计文档发给其他人评审之前,自己先假装是评审人员。你对这份设计文档有什么疑问?然后在发出文档之前把这些问题解决掉。
假期测试
如果你在独家,无法访问网络,那么团队中的其他人是否可以读懂这份文档,并按照你的意图实现文档中的内容?
设计文档的主要目的不是为了知识共享,但这是一种评估清晰度的好办法,让其他人可以为你提供有用的反馈。
流程
设计文档可以帮你在浪费大量时间实现错误的解决方案或解决错误的问题之前获得反馈。获得良好反馈是一门艺术,但那是后话了。现在,让我们来讨论下如何为设计文档获取反馈。
首先,参与项目的每个人都应该参与设计过程。即使有很多决定是由技术主管做出的,那也没关系,至少每个人都应该参与讨论,并接收他们的设计。
其次,设计的过程并不一定是盯着白板,在上面画出各种想法。你可以动起手来,建立各种可能的解决方案原型。这与在写好设计文档之前就开始写代码是不一样的。你完全可以随意写一些一次性的代码来验证你的想法。为了确保你的代码只是用于概念验证,原型代码都不能合并到 master 上。
在你了解了如何进行项目之后,请执行以下步骤:
- 请你团队中经验丰富的工程师或技术负责人来评审你的文档。理想情况下,评审人员应该是一个受到尊重并且对问题边缘情况已经很熟悉的人。
- 在有白板的会议室里进行评审。
- 向评审人员描述你正在解决的问题(这是非常重要的一步,不要跳过它!)。
- 然后向评审人员解释你想要怎样实现你的想法,并说服他们这是正确的解决方案。
在开始正式编写设计文档之前完成所有这些步骤,可以让你在投入更多时间并敲定解决方案之前尽快获得反馈。通常情况下,即使实现方式可以保持不变,评审人员仍然会指出一些需要你覆盖到的极端情况,或者指潜在的不明确的地方,并预测你以后可能会遇到的困难。
然后,在你为设计文档写了粗稿之后,让之前的评审人员再次阅读它,并在设计文档的“标题和人物”部分写下他们的名字,作为对评审人员的鼓励,也表示他们是有责任对自己的评审行为负责的。
在添加评审人员名字时,可以考虑为特定的问题添加不同的评审人员(例如 SRE 和安全工程师)。
在完成评审之后,请将设计文档发给你的团队,以便获得额外的反馈。我建议把这个时间限制在 1 周左右,以避免延期。尽量在一周内解决他们留下的问题。
最后,如果你和评审人员及其他阅读该文档的工程师之间存在争议,我强烈建议你将这些争议放在文档的“讨论”部分。然后,与各方召开会议讨论这些分歧。
如果一个主题超过了 5 条评论,那么进行面对面讨论往往会更有效率。请记住,即使无法让每个人都达成共识,你仍然可以拍板。
在最近与 Shrey Banga 谈论此事时,我了解到 Quip 有一个类似的过程,只是除了让团队中经验丰富的工程师或技术负责人来充当评审人员之外,他们还建议让不同团队的工程师评审设计文档。我没有尝试过这个,但可以肯定的是,这样有助于从拥有不同视角的人那里获得反馈,从而进一步提高文档的质量。
在完成上述所有步骤之后,接下来就可以开始实现了!在实现设计的过程中,可以将设计文档视为活动的文档。在对实现方案做出调整时,也一并更新文档,这样你就不需要向所有利益相关者反复解释这些变化。
那么,我们如何评估一份设计文档成功与否?
我的同事 Kent Rakip 对这个问题的回答是:如果能够获得正确的投资回报率(ROI),那么设计文档就是成功的。也就是说,一份成功的设计文档可能会导致:
- 你花了 5 天时间编写设计文档,迫使你对技术架构的不同部分进行了充分的思考。
- 你从评审人员那里获得反馈,知道架构中某些部分具有较高的风险。
- 你决定先解决这些问题,以便降低项目的风险。
- 3 天后,你发现这些问题要么不可能发生,要么比你原先想象的要困难得多。
- 你决定停止这个项目去做其他工作。
在本文开头,我们说设计文档的目的是确保正确地完成工作。在上述的示例中,因为有了设计文档,你只花了 8 天时间而不是浪费了几个月才决定要中止项目。在我看来,这似乎也是一个非常成功的结果。
https://medium.freecodecamp.org/how-to-write-a-good-software-design-document-66fcf019569c