作为一名软件工程师,我花了很多时间阅读和编写设计文档。在阅读了数百份设计文档后,我亲眼目睹了优秀的设计文档与项目最终成功之间的密切关系。
这篇文章是我尝试描述如何让设计文档变得出色。
本文分为 4 个部分:
- 为什么要编写设计文档
- 设计文档中应包含哪些内容
- 如何编写
- 围绕它的进程
为什么要编写设计文档?
设计文档(也称为技术规范)是关于您计划如何解决问题的描述。
已经有很多文章解释了为什么在开始编码之前编写设计文档很重要。所以我在这里想说的是:
设计文档是确保正确完成工作的最有用的工具。
设计文档的主要目标是通过迫使您仔细思考设计并收集他人的反馈来提高您的效率。人们通常认为设计文档的目的是向其他人传授某个系统或作为以后的文档。虽然这些可能是有益的副作用,但它们本身并不是目标。
一般来说,如果你正在从事的项目可能需要 1 个工程师月或更长时间,那么你应该编写一份设计文档。但不要止步于此——许多较小的项目也可以从迷你设计文档中受益。
太棒了!如果你还在读这篇文章,那说明你相信设计文档的重要性。然而,不同的工程团队,甚至同一团队的工程师,编写的设计文档往往大不相同。所以让我们来谈谈一份好的设计文档的内容、风格和流程。
设计文档中应包括哪些内容?
设计文档描述了问题的解决方案。由于每个问题的性质不同,您自然会希望以不同的方式构建设计文档。
首先,以下是您至少应该考虑 在下一个设计文档中包含的部分列表:
头衔和人物
您的设计文档的标题、 作者(应与计划从事该项目的人员名单相同)、 文档的审阅者(我们将在下面的流程部分详细讨论)以及本文档的最后更新日期。
概述
公司每位工程师都应该理解并使用它来确定阅读文档其余部分是否有用的高度概括的摘要。摘要最多应为 3 段。
语境
手头问题的描述、为什么这个项目是必要的、人们需要知道什么来评估这个项目,以及它如何适应技术战略、产品战略或团队的季度目标。
目标和非目标
目标部分应该:
描述项目对用户的影响——你的用户可能是另一个工程团队,甚至是另一个技术系统
指定如何使用指标来衡量成功——如果您可以链接到跟踪这些指标的仪表板,则可以获得加分
非目标同样重要,它描述了您不会解决哪些问题,以便每个人都达成共识。
里程碑
一份可衡量的检查点列表,以便您的 PM 和经理的经理可以浏览并大致了解项目不同部分的完成时间。如果项目持续时间超过 1 个月,我建议您将项目分解为面向用户的主要里程碑。
使用日历日期,这样您就可以考虑不相关的延迟、假期、会议等。它应该看起来像这样:
Start Date: June 7, 2018Milestone 1 — New system MVP running in dark-mode: June 28, 2018Milestone 2 - Retire old system: July 4th, 2018End Date: Add feature X, Y, Z to new system: July 14th, 2018
如果某些里程碑的预计到达时间 (ETA) 发生变化,请在此处添加一个[Update]小节,以便利益相关者可以轻松看到最新的估计值。
现有解决方案
除了描述当前的实现之外,您还应该通过高级示例流程来说明用户如何与该系统交互和/或数据如何流经该系统。
用户故事是构建这一点的好方法。请记住,您的系统可能拥有不同类型的用户,并且使用情况也不同。
建议的解决方案
有些人将其称为技术架构部分。再次尝试通过用户故事来具体化这一点。可以随意添加许多子部分和图表。
首先提供一幅大图景,然后填写大量细节。目标是,您可以写出这样的世界,然后在某个荒岛上度假,团队中的另一位工程师只需阅读它并按照您描述的方式实施解决方案即可。
替代解决方案
在提出上述解决方案时,您还考虑了什么?替代方案的优缺点是什么?您是否考虑过购买第三方解决方案(或使用开源解决方案)来解决这个问题,而不是自己构建?
可测试性、监控和警报
我喜欢加入这一部分,因为人们经常把它当作事后才想到的东西,或者完全跳过它,而当事情发生故障而他们不知道原因和原因时,它几乎总是会回来困扰他们。
跨团队影响
这将如何增加值班和开发运营的负担?这将花费多少钱?它会导致系统延迟回归吗?它会暴露任何安全漏洞吗?有哪些负面后果和副作用?支持团队如何将此事传达给客户?
未决问题
您不确定的任何未决问题、您希望读者参与的有争议的决定、建议的未来工作等等。此部分的一个俏皮名称是“已知的未知数”。
详细范围和时间表
本节主要供从事该项目的工程师、他们的技术主管和经理阅读。因此本节位于文档的末尾。
本质上,这是您计划如何以及何时执行项目每个部分的细分。要准确确定范围,需要做很多工作,因此您可以阅读这篇文章以了解有关范围的更多信息。
我还倾向于将设计文档的这一部分视为正在进行的项目任务跟踪器,因此每当我的范围估算发生变化时,我都会更新它。但这更多的是个人喜好。
如何编写
既然我们已经讨论了好的设计文档应该包含哪些内容,那么让我们来谈谈写作风格。我保证这与你的高中英语课不同。
写得尽可能简单
不要试图像你读过的学术论文那样写作。它们是为了给期刊审稿人留下深刻印象而写的。你的文档是为了描述你的解决方案并获得队友的反馈而写的。你可以使用以下方法获得清晰度:
- 简单的话
- 短句
- 项目符号列表和/或编号列表
- 具体的例子,例如“用户 Alice 连接了她的银行账户,然后...”
添加大量图表
图表通常可用于比较多个潜在选项,并且图表通常比文本更容易解析。我使用 Google Drawing 创建图表时运气不错。
专业提示:请记住在屏幕截图下方添加指向图表可编辑版本的链接,以便当情况不可避免地发生变化时,您可以轻松地更新它。
包括 数字
问题的规模通常决定了解决方案。为了帮助审阅者了解世界状况,请包含实际数字,例如数据库行数、用户错误数、延迟 — 以及这些数字如何随使用量而变化。还记得 Big-O 符号吗?
尝试变得有趣
规范不是学术论文。此外,人们喜欢阅读有趣的东西,所以这是吸引读者的好方法。不过,不要过度使用,以免偏离核心思想。
如果你和我一样,很难幽默,Joel Spolsky(显然以喜剧天赋而闻名……)有这个建议:
最简单的搞笑方式之一就是在不需要时具体化[… 例如:] 不要说“特殊利益”,而要说“左撇子鳄梨农民”。
进行怀疑论者测试
在将您的设计文档发送给其他人进行审阅之前,请假装自己是审阅者,仔细阅读一下。您对这个设计可能有什么问题和疑虑?然后先发制人地解决它们。
进行假期测试
如果您现在去度长假并且没有互联网接入,您的团队中的某个人可以阅读文档并按照您的意图实施它吗?
设计文档的主要目标不是知识共享,但这是一种评估清晰度的好方法,以便其他人可以真正给你有用的反馈。
过程
设计文档可帮助您在浪费大量时间实施错误的解决方案或错误问题的解决方案之前获得反馈。获得良好反馈有很多技巧,但那是以后的文章的内容。现在,我们只具体讨论如何编写设计文档并获得反馈。
首先,参与该项目的每个人都应该参与设计过程。如果技术主管最终推动了很多决策,那也没关系,但每个人都应该参与讨论并认同设计。因此,本文中的“你”实际上是复数的“你”,包括项目中的所有人。
其次,设计过程并不意味着你要盯着白板理论化想法。你可以自由地动手,为潜在的解决方案制作原型。这与在编写设计文档之前开始为项目编写生产代码不同。不要那样做。但你绝对应该自由地编写一些粗制滥造的一次性代码来验证一个想法。为了确保你只编写探索性代码,请制定一条规则,即这些原型代码都不会合并到 master 中。
此后,当您开始对如何开展项目有了一些想法时,请执行以下操作:
- 请团队中经验丰富的工程师或技术主管担任审阅者。理想情况下,此人应受人尊敬和/或熟悉问题的边缘情况。如有必要,可以用珍珠奶茶贿赂他们。
- 走进一间带着白板的会议室。
- 向这位工程师描述你正在解决的问题(这是一个非常重要的步骤,不要跳过!)。
- 然后解释您所想的实施方案,并说服他们这是正确的做法。
在开始编写设计文档之前完成所有这些工作,可以让您尽快获得反馈,而无需投入更多时间并执着于任何特定解决方案。通常,即使实现保持不变,您的审阅者也能够指出您需要涵盖的极端情况,指出任何潜在的混淆区域,并预测您以后可能遇到的困难。
然后,在您编写完设计文档的草稿后,请同一位审阅者再次通读一遍,并在设计文档的标题和人员部分添加其姓名作为审阅者,以盖章批准。这为审阅者创造了额外的激励和责任。
在这方面,考虑针对设计的特定方面添加专门的审阅人员(例如 SRE 和安全工程师)。
在您和审阅者签字同意后,请随时将设计文档发送给您的团队,以获取更多反馈和知识共享。我建议将此反馈收集过程的时间限制在 1 周左右,以避免长时间延误。承诺在那一周内解决人们留下的所有问题和评论。留下评论 = 坏运气。
最后,如果您、审阅者和其他阅读文档的工程师之间存在很多争议,我强烈建议将所有争议点汇总到文档的讨论部分。然后,与各方安排一次会议,亲自讨论这些分歧。
当讨论主题超过 5 条评论时,进行面对面讨论往往更有效率。请记住,即使每个人都无法达成共识,您仍有责任做出最终决定。
最近,在与Shrey Banga讨论此事时,我了解到 Quip 也有类似的流程,除了让团队中经验丰富的工程师或技术主管担任审阅者之外,他们还建议让其他团队的工程师审阅文档。我还没有尝试过这种方法,但我确实认为这有助于从具有不同观点的人那里获得反馈,并提高文档的整体可读性。
完成上述所有操作后,就可以开始实施了!为了获得额外的加分,请在实施设计时将此设计文档视为一份活文档。每次您了解到导致您更改原始解决方案或更新范围的内容时,请更新文档。当您不必向所有利益相关者一遍又一遍地解释事情时,您会感谢我的。
最后,让我们真正地讨论一下:我们如何评估设计文档的成功?
我的同事Kent Rakip对此有一个很好的答案:如果工作的投资回报率正确,设计文档就是成功的。这意味着成功的设计文档实际上可能会产生这样的结果:
- 你花了 5 天时间编写设计文档,这迫使你思考技术架构的不同部分
- 你从审阅者那里得到的反馈X是所提议的架构中最危险的部分
- 您决定首先实施X以降低项目风险
- 三天后,你发现这X是不可能的,或者比你最初设想的要困难得多
- 你决定停止这个项目,转而优先处理其他工作
在本文开头,我们说过设计文档的目的是确保完成正确的工作。在上面的例子中,多亏了这份设计文档,您才只花了 8 天时间,而不是浪费几个月的时间,然后放弃这个项目。在我看来,这似乎是一个相当成功的结果。
您被添加为规范的审阅者,您应该做什么?
我的好朋友兼榜样Joy有以下很好的建议:
当您签署规范时,您应该了解以下问题的答案。
项目
- 这个项目解决了什么问题?我们如何知道它是否成功?
元
- 这个项目正在做出的重大决策是什么?其影响是什么?
- 项目中最复杂或风险最大的部分是什么?如何处理?
技术设计
- 您在 5 分钟内能想到的最简单的替代实现是什么?相对于此,所提议的方法有哪些优点/缺点?所提议方法中的额外实现时间能带来哪些改进?值得吗?注意:这并不意味着您将在 5 分钟内想出更好的方法。它只是为您提供一些更具体的东西来与所提议的实现进行比较。
- 这个项目的关键技术决策是什么?这些决策的结果是怎样的?
- 该项目与哪些外部系统交互?它增加了多少规模?它是否遵循当前的最佳实践和模式?它是否符合长期发展方向?它是否意味着未来的承诺或技术债务?
- 您知道哪些信息,而作者可能不知道?您之前见过类似的解决方案吗?(成功与否)他们使用的系统中是否存在不明显的边缘情况?是否存在您认为实际上需要一段时间的“简单”实现?
监控/警报
- 项目期间最可能出现的故障模式是什么(例如中期推出)
- 项目结束后最有可能的失败模式是什么?
- 上述情况将如何监控和检测?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。