【翻译】如何写出一份优秀的设计文档

真的要好好写文档

Posted by MeloGuo on September 25, 2020

作为一名软件工程师,我花费了许多时间来阅读和编写设计文档。在看了几百份这样的文档后发现,优秀的设计文档与项目最终的成功有很大的关系。

在这篇文章中,我尝试去阐述是什么让一份设计文档如此重要

这篇文章可分为 4 个部分:

  • 为什么要写设计文档
  • 设计文档应该包含什么内容
  • 如何写
  • 具体过程

为什么要写设计文档?

设计文档(也被称为技术手册)是对你计划如何解决问题的描述。

已经有许多文章在阐述为什么要在潜心编码之前写一个设计文档。所以我的观点是:

设计文档是确保正确完成工作最有用的工具。 ** 设计文档是通过强迫你思考完整的设计流程并且从他人处收集反馈的方式来使你的工作更有效率。人们经常认为设计文档的目的是为了以后教会他人了解系统或者服务。虽然这些可能是有益的副作用,但他们本身并不是目标。

通常来说,如果你的项目需要花费一个工程师一个月以上,那就应该写设计文档。但不要就此止步 — 许多更小型的项目也可以从小型的设计文档中受益。

棒!如果你读到了这里,那么一定是认同设计文档的重要性。然而,不同的工程师团队,甚至是在一个团队中不同的工程师写出的设计文档都有很大的不同。那么我们就来谈谈一个优秀的设计文档的内容、风格和流程。

设计文档应该包含什么内容?

设计文档描述了问题的解决方法。既然每个问题的性质都不一样,自然就会希望你的设计文档结构不同。

首先,以下是你至少应该考虑在下一份设计文档中包含的章节列表:

标题和人员

设计文档的标题,作者,审查人员以及最近的更新日期。

概述

一个高度的总结,公司的每个工程师都应该能看懂,并且以此来决定是否阅读剩下的内容。此部分最多应有 3 个段落。

背景

描述下手头的问题,为什么要做这个项目,人们需要知道哪些内容来评估这个项目,它是如何融入技术战略、产品战略或者团队季度目标的。

目标与非目标

目标章节应该有:

  • 描述用户驱动对项目的影响 - 你的用户可能是另外一个工程师团队或者甚至是另外一个技术系统
  • 制定如何使用指标来衡量成功与否 - 如果你能可视化指标进度将会非常加分

非目标同样的重要,讲清楚那些你讲不会解决的问题,这样大家就能达成一致。

里程碑

一个可衡量的检查点列表,这样你的 PM 或者 Leader 就能大致知道项目的不同部分何时完成。如果项目超过一月以上,我推荐你把项目分解成以面向用户为主的里程碑。

使用像日历(译者:企业微信的日历就可以)这种工具,这样你就可以考虑到不相关的任务延迟、休假、会议等。它应该看起来像这样:

开始日期:2018.06.07  里程碑 1 - 新系统的 MVP 可运行暗黑模式:2018.06.28 里程碑 2 - 下线旧系统:2018.07.04 结束日期:添加特性 X,Y,Z 到新系统:2018.07.14

如果其中一些里程碑的预计时间发生变化,则在此增加一个 [更新]  小节,以便利益相关方可以很容易的看到最新的估时。

现有方案

除了描述当前的实现外,你还应该通过一个高层次的示例流程来说明用户如何与这个系统交互或者数据如何流经这个系统。

一个需求描述可以很好的框定这一点。请记住你的系统可能有不同类型的用户需要不同类型的用例。

提议方案

有些人称之为技术架构部分。还是那句话,试着通过一个需求描述来具体化它。可随意包含子章节和各种图表。

先提供一个大框架,然后再填充细节。要达到这样一种境界,写好它,然后你就能安心出去度个假,只要团队里的另一个工程师看了之后,按照你描述的方案实施就可以了。

替代方案

在想出上述解决方案时,你还考虑了什么?替代方案的优缺点是什么?你是否考虑过购买第三方的解决方案 - 或者使用开源的解决方案 - 来解决这个问题,而不是自己建立一个解决方案?

测试,监控和报警

我很喜欢加上这部分内容,因为人们往往把这部分当作是事后诸葛亮,或者是一并跳过。但当事情搞砸时候这部分的缺失总是会反咬他们一口,并且他们不知道发生了什么,也不知道为什么发生。

跨团队的影响

这将如何增加实时可用性和开发运营的负担? 这将会花多少钱? 会不会造成潜在的系统回滚风险? 会不会暴露任何安全漏洞? 有哪些负面的后果和副作用? 支持团队可能会如何与客户交流此内容?

开放问题

任何你不清楚的问题,有争议的决定,希望读者们能给予权衡,对未来工作的建议等等都可以写在这里。这个部分有一个风趣的名字,叫“已知的未知数”。

细节范围和时间线

此章节大部分情况下会被开发此项目的工程师,他们的领导或者经理阅读。因此这个章节被放到文档的末尾。

从本质上讲,这是对你计划如何以及何时执行项目的每个部分的分解。准确地确定范围有很多内容,所以你可以阅读本篇来了解更多关于范围确定的内容。

我也倾向于把设计文档的这一部分当作一个正在进行的项目任务跟踪器,所以每当我的细节内容预估发生变化时,我就会更新这部分内容。但这更多的是个人的偏好。

如何写

现在我们已经谈到了有什么内容会成为一个好的设计文档,接下来让我们来谈谈写作的风格。我保证这和你的高中英语课不一样。

尽可能简单

不要尝试去写成你看过的学术论文。它们是为打动期刊审稿人而写的。你的文档是用来描述你的解决方案和从你的同事那里获得反馈。你可以使用以下方式来表达的简洁:

  • 简单的词语
  • 短小的句子
  • 无序/有序列表
  • 具体的例子,例如:“用户 Alice 连接到她的银行账户,然后……”

添加大量图表

图表对于比较几个潜在的选项往往很有用,而且图表通常比文本更容易解析。我很乐于使用 Google Drawing 来创建图表。

小技巧:记得在可编辑图表的截图下添加一个链接,这样当图表发生变化时,你就可以方便的更新它。

包含数字

问题的规模通常决定了解决方案。为了帮助审查者了解项目的状态,包括真实的数字,如 DB 的行数,用户的错误,延迟以及这些内容如何随着使用情况而拓展。还记得大 O 标记法吗?

尝试有趣

一份手册并不是学术论文。另外,人们喜欢阅读有趣的玩意儿,所以这是一个吸引读者的好方法。不过不要过度到偏离核心思想的地步。

如果你想我一样不知道该怎么有趣,Joel Spolsky 有个建议:

想要变得有趣最简单的方法之一,就是在不需要的时候,具体一点[……例:]不要说 “特殊利益”,而是说 “左手牛油果农”。(译者:这个我是真不懂)

怀疑测试

在发送你的设计文档给别人审阅之前,假装自己是审查人员的过一遍。你关于这个设计可能会有什么样的问题和疑惑?先发制人的解决这些问题。

度假测试

如果你现在要去一个没有网络连接的地方度一个长假,你团队上有人能够阅读这份文档并且按照你预想的方式实现出来吗?

设计文档的主要目标不是分享知识,但这是一个很好评估方式以便于其他人能够给你真正的有用的反馈。

具体过程

设计文档可以帮助你在你浪费大量时间实现错误的解决方案或解决了错误的问题之前获得反馈。获得好的反馈绝对是一门艺术,但这是以后的文章要谈论的内容。现在,我们只具体的谈谈如何编写设计文档并获得反馈。

首先,在项目中工作的每个人都应该是设计过程的一分子。如果技术负责人最终推动了许多决策,那也没关系,但每个人都应该参与讨论,并为设计买单。所以本文中的“你”是一个复数的“你”,包括了项目中的所有人员。

其次,设计过程并不意味着你盯着白板冒出的理论化的想法。你可以随意的动手,对潜在的解决方案进行原型设计。这在写设计文档之前就开始为项目写生产代码是不一样的(不要这样做)。但你绝对应该自由的写一些黑客式的即兴代码来验证一个想法。为了确保你只写探索性的代码,可以规定这些原型代码都不要合并到主分支中。

之后,当你开始对如何进行项目有了一些想法,就可以进行以下工作:

  1. 询问一位有经验的工程师或者技术负责人做你的审查者。理想情况下,这应该是一个很受尊敬的人或熟悉问题的边缘案例的人。必要时可以用奶茶贿赂他们。
  2. 去一个有白板的会议室。
  3. 向这位工程师描述你要解决的问题(这步非常重要,不要跳过!)。
  4. 然后阐述下你脑海中的实现方案,并说服他们这是值得采纳的正确方案。

在你开始写设计文档之前就做这些工作,可以让你在投入更多的时间和对任何具体的解决方案产生依赖之前,尽快得到反馈。通常情况下,即使实现方式保持不变,你的审查人也能指出你需要覆盖的边缘案例,指出任何潜在的混乱区域,并预测你以后可能遇到的困难。

然后,在你写完设计文档的草稿后,让同一个审查人再读一遍,并在设计文档的标题和人员薄粉加上他们的名字作为审查人。这样可以为审查人创造额外的激励和责任感。

在这一点上,考虑为设计的特定方面添加专门的审查人(如 SRE 和安全工程师)。

一旦你和审查人签了字,可以随时将设计文档发给你的团队,以获得额外的反馈和知识共享。我建议将这个反馈收集过程的时间限制在 1 周左右,以避免长时间的延迟。承诺在一周内解决人们留下的所有问题和评论。让评论悬而未决 = 坏的报应。

最后,如果你、你的审稿人和其他阅读文档的工程师之间有很多争议,我强烈建议将所有的争议点整合到文档的讨论部分。然后,安排不同的当事人开个会,当面讨论这些分歧。

每当一个讨论内容超过 5 条评论时,转为当面讨论往往会更有效率。请记住,即使大家不能达成共识,你仍然要负责做出最后的决定。

最近在和 Shrey Banga 讨论这个问题时,我了解到 Quip 也有类似的流程,除了让你团队中一位经验丰富的工程师或技术负责人作为审稿人外,他们还建议让不同团队的工程师来审阅文档。我还没有尝试过,但我可以肯定地看到这有助于从不同角度的人那里获得反馈,并提高文档的总体可读性。

一旦你完成了以上所有的工作,就可以开始实施了。要想获得额外的分数,请把这个设计文档当作一个活的文档,因为你要实现这个设计。每当你学到一些东西,导致你对原始解决方案进行修改或更新你的范围时,就更新这个文档。当你不需要向所有的利益相关者反复解释的时候,你会感谢我的。

最后,让我们先来谈一谈:我们如何评估一个设计文档的成功?

我的同事 Kent Rakip 有一个好的答案:如果工作的 ROI 正确,一份设计文档就是成功的。这意味着一份成功的设计文档可能会导致这样的结果:

  1. 你要花费 5 天编写设计文档,这迫使你完整思考技术架构的不同部分
  2. 你从审查人那里得到的反馈是, X  是建议架构中风险最大的部分
  3. 你决定先实施 X ,以降低项目风险
  4. 3 天后,你发现 X  要么是不可能的,要么是远比你原来想象的要困难得多
  5. 你决定停止这个项目的工作,而优先考虑其他工作

在本文开头,我们说过,设计文档的目标是确保完成正确的工作。在上面的例子中,多亏了这个设计文档,你没有浪费可能几个月的时间,却在后来中止了这个项目,而是只花了 8 天时间。在我看来,这是一个很成功的结果。

如果你有任何问题或反馈,请在下面留言! 我也很想听听你在你的团队中如何以不同的方式做设计文档。

我在 Plaid(我们正在招聘!快来和我们一起设计和构建一些甜蜜的技术系统)和 Quora 的一些令人难以置信的工程师身边工作,学到了很多以上的知识。

如果你喜欢这篇文章,请在 Twitter 上关注我,了解更多关于工程、流程和后端系统的文章。

著作权声明

本文译自 How to write a good software design doc 译者 郭梓梁,首次发布于 MeloGuo Blog,转载请保留以上链接。