如何编写有效的软件设计文档

Lobsters Hottest 工具

摘要

一份实用的指南,介绍如何编写有效的软件设计文档,概述关键组成部分和最佳实践,这些经验来自作者在 Google 和 Microsoft 的工作经历。

<p><a href="https://lobste.rs/s/kmx6wx/how_write_effective_software_design">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/24 18:00

# 如何撰写有效的软件设计文档 来源:https://refactoringenglish.com/excerpts/write-an-effective-design-doc/ 一份好的设计文档可以为你节省数年的开发时间。撰写设计文档迫使你在浪费大量时间于错误的实现方案或陷入技术死角之前,就重要决策进行深入思考。这也是协调团队成员及合作团队之间设计决策的最佳方式。 我曾在 Google、Microsoft 以及我自己的公司(https://mtlynch.io/projects/)担任开发者期间撰写过设计文档。具体细节可能有所不同,但核心理念始终如一。一份设计文档应当清晰地阐述你所解决的核心难题,并帮助团队成员为你提供反馈。 下面,我将分享撰写有效设计文档的方法,并说明哪些内容应该包含在文档中,哪些则不应该。 - 示例设计文档(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#an-example-design-doc) - 何时应撰写设计文档?(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#when-should-you-write-a-design-doc) - 在设计文档上应投入多少精力?(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#how-much-should-you-invest-into-your-design-doc) - 设计文档中应包含哪些内容?(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#what-belongs-in-a-design-doc) - 决策错误的成本是什么?(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#whats-the-cost-of-getting-it-wrong) - 设计文档的组成部分(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#components-of-a-design-doc) - 标题(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#title) - 元数据(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#metadata) - 目标(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#objective) - 背景(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#background) - 相关文档(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#related-documents) - 目标(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#goals) - 非目标(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#non-goals) - 场景(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#scenarios) - 图表(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#diagrams) - 术语表(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#glossary) - 约束条件(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#constraints) - 服务水平目标(SLOs)(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#service-level-objectives-slos) - 监控/告警(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#monitoring--alerting) - 时间线(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#timeline) - 接口(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#interfaces) - 依赖项/基础设施(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#dependencies--infrastructure) - 安全性(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#security) - 隐私(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#privacy) - 法律考量(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#legal-considerations) - 日志记录(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#logging) - 未决问题(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#open-issues) - 已解决问题(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#resolved-issues) - 已考虑的替代方案(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#alternatives-considered) - 推动设计文档通过评审(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#driving-your-design-doc-through-review) ## 示例设计文档🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#an-example-design-doc) 关于设计文档,我最常被问到的问题是哪里可以找到一份好的范例。我从未见过公开且我认为高质量的设计文档。我所有的设计文档都藏在付费让我撰写它们的公司内部。 因此,我根据这里分享的原则,从头开始撰写了一份设计文档(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/little-moments-design-doc/)。它为一个我正在进行开发的实际 Web 应用(https://codeberg.org/mtlynch/little-moments)设计了架构。 您的浏览器不支持视频标签。我在编写任何代码之前就创建了这份设计文档,并且在实现该应用(https://codeberg.org/mtlynch/little-moments#status)的过程中一直遵循着设计。 - Little Moments 设计文档(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/little-moments-design-doc/) 这个设计比我通常为个人业余项目撰写的要详尽得多,但这大致是我在为职业项目与他人协作时,所创建设计文档的长度和深度。 ## 何时应撰写设计文档?🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#when-should-you-write-a-design-doc) 项目越复杂或风险越高,撰写设计文档的价值就越大。 请考虑以下问题: - 是否需要多人协作来实现该设计? - 该项目是否耗时超过三个月的全职开发工作? - 该实现是否将在生产环境中运行数年? - 该项目是否涉及跨团队协作? - 项目的目标与需求是否不明确? - 是否存在设计阶段就能避免的灾难性风险(例如安全漏洞、法律风险)? 如果你对上述任何一个问题回答了“是”,那么撰写设计文档很可能值得投入精力。如果你对两个或以上问题回答了“是”,那么设计文档几乎肯定值得去做。 ## 在设计文档上应投入多少精力?🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#how-much-should-you-invest-into-your-design-doc) 设计文档可以是一页纸的简单描述,也可以是需要五个不同团队批准签字的 50 页文档。你需要决定多大的详细程度是合理的。 在设计中投入多长时间并没有普遍适用的规则,就像测试代码也没有固定标准一样。正确的投入取决于团队的目标、风险、截止日期和文化。有时候,在设计文档上投入的合理量是零。 ## 设计文档中应包含哪些内容?🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#what-belongs-in-a-design-doc) 如果你在设计文档中指定了所有可能的细节,那基本上就等于在设计阶段就把实现写完了。这将完全违背设计文档的目的。 作为经验法则,你可以通过一个简单的问题来决定某个决策是否应纳入设计文档:如果错了,代价有多大? ### 决策错误的成本是什么?🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#whats-the-cost-of-getting-it-wrong) 并非所有设计决策都同等重要。有些选择在灵活性上有着天壤之别。 例如,如果你用 C++ 构建了一个 Web 应用,却在写了 20 万行代码后意识到 Ruby on Rails 是更好的选择,那么你就陷入了困境。从头重写几乎不可能(https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/),即使你设法用 Rails 编写新代码,仍然要承受维护两种截然不同语言代码的负担。 另一些设计决策则微不足道。例如,如果你的应用要显示 1000 篇文章的列表,是应该一次性全部显示?还是让用户每次看到 20 篇,点击“加载更多”后再显示接下来的 20 篇? 这并不重要。 “加载更多”按钮不属于设计层面的考量。如果你选择了某个方案,用户反馈告诉你错了,你几个小时内就能修复。你无需在设计文档中详述全部思考过程,也绝不应该浪费评审周期去争论这个问题。 ## 设计文档的组成部分🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#components-of-a-design-doc) 下面列出了一些常见的部分,供你在设计文档中包含。通常不需要每份文档都包含所有部分,选择适合你的子集即可。 ### 标题🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#title) 项目首先需要一个标题。这是人们在谈话中提及该项目的方式,因此要追求以下特质: - **简短**:容易脱口而出。 - **有辨识度**:能明确指代该项目。 - **有启发性**:在概念上代表你的项目。 例如,如果你要在应用服务器和数据库服务器之间添加缓存层,**RecencyBank** 就是个好名字。它容易说出口,也描述了项目的目的。而“Project Flying Silver Horse”则是个糟糕的名字,因为它冗长且毫无意义。 ### 元数据🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#metadata) 虽然枯燥但很实用,元数据能帮助读者了解文档的基本背景: - 作者是谁?(姓名 + 电子邮件地址) - 文档创建时间? - 权威 URL 是什么?——尤其是当你的组织使用 `http://go/recency-bank` 这样的短链接重定向(https://golinks.github.io/golinks/)时。 > **元数据** > - **作者**: Michael Lynch([email protected]) > - **状态**: 待评审 > - **创建时间**: 2026-06-22 > - **URL**: http://go/recency-bank-design ### 目标🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#objective) 目标是用一句话解释项目的目的。它应该出现在文档的第一页,并使用所有利益相关者都能理解的白话。 > **目标** 通过在 Trogdor Web 服务器和 Postgres 数据库之间增加缓存层,来改善应用性能。 ### 背景🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#background) 背景部分解释了项目的背景和动机。它应当回答以下问题: - 团队为什么要做这个项目? - 这个项目解决了什么问题? - 之前有没有尝试解决过这个问题? > **背景** 当我们于 2023 年发布 Trogdor Web 应用时,页面加载时间通常为 100 毫秒或更短。三年后,页面加载的中位时间膨胀到了 600 毫秒,这导致用户感觉我们的应用反应迟钝。我们调查了性能下降的原因,发现数据库查询占用了 80% 的页面加载时间。随着数据存储规模的增长,数据库查询变得越来越慢。我们还发现,95% 的数据库查询都是针对同样的 3% 的数据行。这种使用模式非常适合使用内存缓存技术。缓存可以为频繁访问的数据提供更快的服务,并减少所有其他查询的数据库负载。 **你的设计文档在没有外部背景信息的情况下是否依然可读?** 设想一下,你会在团队成员或合作团队阅读设计文档之前对他们说什么。 现在,请意识到有些读者在听取你解释之前就已经看文档了,因此无论他们需要了解什么,都应该放在文档的第一页(https://refactoringenglish.com/excerpts/useful-feedback-on-design-docs/#write-an-introduction-that-makes-sense-to-everyone)。 如果该项目与其他文档有关联,请链接它们,方便读者查找。这些包括: - 来自项目经理或测试对应人员关于该项目的文档(如测试计划、功能规格说明书) - 相关系统的设计文档 - 该项目之前迭代的设计文档 > **相关文档** > - **测试计划**: http://go/recency-bank-test-plan > - **Trogdor 性能报告**: http://go/trogdor-perf-2026 ### 目标🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#goals) 目标部分描述了你对这个项目的高层次目标。它应该在逻辑上与背景部分相连,并说明完成实现后世界会变成什么样。 避免用实现细节来描述目标。你的目标应传达项目如何让用户、团队或公司受益。 ❌ 错误示例 - 在基础设施中添加 Kubernetes。 - 尽量减少因部署新版本应用导致的中断。 ✅ 正确示例 - 提升 Trogdor Web 应用的用户感知响应速度。 - 降低数据库服务器负载。 > **目标** > - 提升 Trogdor Web 应用的用户感知响应速度。 > - 降低数据库服务器负载。 ### 非目标🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#non-goals) 目标定义了项目的范围,而非目标部分则明确了哪些不在范围之内。 有没有哪些目标读者可能错误地认为在项目范围内?如果有,请作为明确的非目标加入。 > **非目标** > - 创建通用可重用的缓存系统 > - 我们为 Trogdor Web 应用添加的缓存层将做应用级别的优化。在其他系统上重用此缓存不在范围内。 > - 地理位置感知缓存 > - 未来可能有必要支持靠近最终用户地理位置的缓存以减少延迟,但 v1 版本不考虑。 ### 场景🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#scenarios) 如果你的目标是“在图表上添加‘通过 URL 分享’按钮”,读者可能无法理解这在实际中意味着什么。 场景部分允许你向读者描绘完成后系统在真实世界中如何工作的画面。 > **场景:通过 URL 分享报告** > 1. Bob 在他的 KeyMetrics 仪表板中创建了一个自定义报告。 > 2. Bob 导航到菜单栏,点击“分享 > 通过 URL”。 > 3. Bob 将 URL 通过电子邮件发送给他的同事 Charlie。 > 4. Charlie 点击链接,以只读模式看到了 Bob 报告的精确副本。 ### 图表🔗(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/#diagrams) 图表非常有价值,尽管可能看起来不那么明显。 作为设计作者,你直观地理解计划中的各个部分如何组合在一起。你在脑海中可以看到整个架构。但评审者没有这个心理图像,因此让他们最快看到的方法就是画一幅图。 架构图(https://refactoringenglish.com/excerpts/write-an-effective-design-doc/architecture-diagram.svg) 展示简单 Web 应用架构的示例图表。 如果你不确定图表中应该包含什么,请思考这些问题: - 数据如何在你的系统中流动? - 系统的不同组件如何适配在一起? - 你的系统如何与其依赖项和下游客户端交互? - 你的系统定义了哪些通信协议? 请选择易于编辑的绘图工具。我曾见过开发者在白板上画出漂亮的图表并拍照放入设计文档。初版看起来很棒,但之后他们就被困在这个图上,因为无法编辑照片,只能从头重绘。 Excalidraw(https://excalidraw.com/)、draw.io(https://www.drawio.com/)和 Google Drawings(https://docs.google.com/drawings/)是流行的绘图工具,

相似文章

google-labs-code/design.md

GitHub Trending (daily)

DESIGN.md 是来自 Google Labs 的格式规范,它将 YAML 设计令牌与 Markdown 文本相结合,为编码代理提供对设计系统的结构化理解,包括 lint 工具和 diff 比较。