2026-07-20-技术写作-关于设计文档

6390 个字
32 分钟
2026-07-20-技术写作-关于设计文档

TLDR#

软件设计是软件工程中的一个重要环节。沟通软件设计决策的基础工具——但沟通本身很难,写设计文档也一样难。

在确立了我们要构建的产品或系统的需求之后,我们要制定计划、做出决策,考虑如何用软件最好地实现这些需求。如何用一份设计文档来推动就软件设计达成一致的过程,并为当前及未来的实现者、维护者以及该软件的其他相关方把这份设计记录下来是很重要的一环。

即使是AI时代,文档写作也仍然是一个很重要的能力。这里主要关于设计文档的方法论与过程论开展

设计文档的方法论#

写作目标#

  • 记录软件设计。
  • 澄清正在解决的问题。
  • 充当进一步细化设计的讨论平台。
  • 解释这些决策背后的推理,以及在决策中做出的权衡。
  • 列出备选设计,以及它们为何没有被选中。
  • 帮助未来的维护者及其他相关方理解为什么当初选择了这个设计。

非目标#

  • 确立软件的非技术性需求。
  • 让一个完全不了解该软件背景的人也能独立看懂(但文中的链接应当引导读者去获取所缺的背景知识)。
  • 充当产品或系统的用户文档。
  • 适用于记录非软件类的设计,比如"设计文档"本身的设计。

概述#

主要的设计思想是:用一份文档来非正式地描述软件设计。

在选定实现方案之前多走这一步,是因为实践已经证明,用一个完整可运行的实现去逐步演进早期的软件设计,效率很低。出于类似的原因,那些试图理解一个既有软件系统的维护者,往往很难仅凭阅读源代码就搞清楚那些根本性的设计决策。

写一份设计文档,开篇先解释这个软件设计的目标、它如何融入更宏观的图景,以及为什么手头这个问题复杂到值得写一份设计文档。之所以明确列出目标与非目标,是为了促使人们去认真思考它们。

文档接着要给出一段简短的设计概述,不铺陈所有细节。概述之后是详细设计部分,那里包含了大部分内容,描述为什么选择了这个设计,以及这个软件设计究竟是什么。

然后是若干关于横切关注点(比如隐私和安全)的章节,会从各自的视角直接阐述设计与它们的关系。

最后我们简要说明考虑过哪些备选方案,以及它们为什么没被选中。

综上所述,设计文档可以被设计成一个高效的设计文档记录与讨论平台,作者可以在实际内容和形式上有很大的自由发挥空间,以最好地表达其设计。

详细设计#

设计软件的过程,理想情况下应当具备以下特性:

  • 汲取团队内部及周边领域专家的经验。
  • 能灵活应对软件需求的变化。
  • 为初始实现产出一份指南。
  • 为实际落地的软件产出一份准确的设计文档。
  • 产出一个在既定约束(如时间和资源)内可实现的设计。
  • 快速确立某个选定的设计是可行的。
  • 快速确立某个选定的设计不可行,进而产出一个可行的设计。
  • 降低设计不可行的风险。
  • 产出简单的设计。
  • 如果情况合适,得出"已存在现成方案、无需再做设计"的结论。

有些要求看似冗余,但其中有些是无法同时达成的。

要证明一个系统能否被实现,最直接的方式就是把它实现出来(MVP);但这可能耗时太久,来不及快速确立什么才是正确的设计,而且等你在旧需求下证明了设计可行时,需求可能早已变了。

在这个权衡空间里,设计文档扮演着关键角色——它既易于协作、形式非正式,又相对详尽、并能随时间更新:

  • 借助现代协作软件(如 Google Docs),团队内外的专家都能协作完成最终文档。
  • 非正式的特性使得内容和形式可以针对手头的设计问题量身定制,从而成为一种高效的设计记录方式。
  • 同样的非正式性降低了"修改成本"。

软件设计的工具箱里还有诸如"概念验证(proof of concept)""微基准测试(micro benchmark)""白板讨论(white board discussion)"之类的东西。虽然逐一解释它们超出了本设计文档的范围,但它们理应被视为软件设计过程的一部分。例如,在设计文档里指向一个概念验证,就是确立设计可行性的绝佳方式。

设计文档与其他系统的关系#

设计文档与其他系统的关系
设计文档与其他系统的关系

设计文档是作为软件设计开发工作的一部分而写就的。它通过软件设计的其他环节——比如白板讨论和设计评审——得到信息补充与反复打磨。

软件设计主要由项目需求驱动,如果适用的话,也由用户界面设计驱动。需求(无论以何种形式表达)定义了一段软件应该做什么,而设计确立了如何实现以及为什么选择那个设计。设计进而指导实现,实现又反过来反馈给设计(当设计遭遇现实时,通过更新设计来体现)。

结构#

元信息 > 背景、范围与目标 > 概述 > 详细设计 > 横切关注点 > 备选方案

设计文档的结构要让读者能够高效且有效地深入主题。文档从相对高层的内容开始,然后逐渐深入到设计的细节。

阅读结构
阅读结构

这样就让读者能够快速评估设计的背景、范围和目标,并对设计有一个基本的理解;然后可以选择是否通读整篇文档。

Metadata#

设计文档应当始终有一个标题,并立即注明作者作为主要联系人,以及最后更新日期。注明状态有助于给读者设定预期,让他们知道文档的完整程度和确定程度。有用的状态包括:

enum[ ] DesignDocState { UNKNOWN = 0; INCOHERENT_RAMBLING = 1; DRAFT = 2; FINAL = 3; IMPLEMENTED = 4; OBSOLETE = 5; };

(未知;语无伦次的胡言乱语;草稿;终稿;已实现;已废弃。上面这段代码片段是特意插进来的,用以进一步说明后文的观点——复制粘贴无关的代码片段并不是个好主意。)

背景、范围与目标#

文档应当首先确立设计的背景和范围。这可以用一段或多段文字来完成。这一部分应当包含"目标"和"非目标"的要点列表,理由有三:

  • 这是一种高效的方式,让读者迅速搞清楚设计想要达成什么、又不想达成什么。
  • 它可以用来评估详细设计是否确实说清了那些目标是如何达成的。
  • 它迫使作者真正对范围做出决断。

我不会去发明一个新的存储系统
我不会去发明一个新的存储系统

概述#

接下来,文档给出设计的概述。这能帮助读者理解整体思路,从而更容易评估各种细节是如何与设计相关联的。要认识到很重要的一点:设计文档不应当在从头读到尾的过程中"制造悬念"。恰恰相反,信息应当尽可能快地给出,结构上应当力求避免把相关信息分隔得太远。

详细设计#

这一部分酌情解释设计、它的各种权衡以及带来的后果。具体内容在很大程度上取决于所设计的东西是什么,并且会因系统、API、前端等各种类型而差异极大。作者被明确授权去选择最契合其设计的形式。关于详细设计部分应包含哪些内容,参见下文的"详略程度"。

横切关注点#

可以有一个或多个章节,从各自特定的视角谈论特定的关注点。虽然整个设计都应把它们纳入考量,但专门的章节能确保它们被正视,并凸显设计是如何应对它们的。这类关注点的例子有:隐私、安全、可扩展性和监控。

考虑过的备选方案#

这一部分是文档结构中固定的组成部分,因为它迫使作者去思考:为达成设计目标,还有哪些备选路径可用。备选方案可以是其他可能的设计,也可以是使用某个几乎能满足需求的既有系统、购买某款标准软件,或者干脆什么都不做。

详略程度#

如前所述,设计文档应当是一个高效的设计讨论与记录平台。文档越长,就越难以消化和修改。因此文档应当"能多短就多短,但该多长就多长"。

关于文档何时过于详细,无法给出确切的指导原则,但有一些迹象表明它可能过头了:

  • 规定了那些对设计并非至关重要的 API。
  • 复制粘贴了只与设计部分相关的源代码。
  • 原始数据。
  • 要点列表里为了凑数而多出一项、并无正当理由(比如为了自我指涉地玩梗)。

给定一份设计文档,一个在该主题上已有经验、或愿意投入去获取该经验的软件工程师,应当能够据此实现这份设计。同理,一个在该主题上有经验的"讲道理的软件工程师",应当能够读懂设计为什么这样选,哪怕他并不认同其结论。

设计文档本身并不负责为任何读者(无论其先前经验如何)提供进入该主题的全部背景,但它应当提供链接,使读者能够建立起跟上后文所需的完整背景。

生命周期#

文档创建#

在设计文档生命周期的早期,重大改动比后期更可能发生——后期设计更加稳定。因此文档的早期迭代应当尽可能轻量,好让修改迅速、让作者对修改的抵触降到最低。

在文档早期阶段,可以采用白板讨论、用要点列表勾勒章节等技巧。

虽然文档本身是非正式的,但初始搭建可以通过使用模板来加速,或者用那个久经考验的技巧——把自己上一次写的设计文档复制粘贴过来。使用这些模板有助于确保最低限度的内容覆盖,并减少样板式的重复劳动。

Canary rollout#

当文档趋于稳定后,明智的做法是先把它分享给一小批"金丝雀读者"。这些人往往是参与过早期白板讨论和设计探讨的同伴。通过把他们的反馈吸收进设计文档,我们能确保没有重大问题被遗漏,并在向更大范围传阅之前确保设计总体上是站得住脚的。

正式发布(Rollout)#

此时,文档被分享给更大范围的团队及其他相关方法。鼓励读者通过行内评论提问和提建议,作者则予以回复。如有必要,应更新文档以回应这些反馈。

最终,设计被宣布为终稿。这往往是非正式地发生的——其标志常常是:人们开始动手实现这个设计了。

安全与隐私考量#

设计文档应该设有专门的章节来阐述安全与隐私考量,以及其他适用的横切关注点,以确保它们得到充分的处理。

其他考虑#

白板讨论 系统往往过于复杂,无法通过一次白板讨论来表达,而那些没有亲自参与讨论的人可能会缺少背景。话虽如此,白板讨论仍是个很好的开端,能在真正动笔写下来之前,以一个轻量的流程勾勒出设计的要点。

敏捷 "做那件能行得通的最简单的事"通常是个好主意,但当这件事包含大量样板、或者累积起来复杂到人人都跟不上进展时,它就不再有趣了。如果"能行得通的最简单的事"本身仍然很复杂,那么设计文档或许能帮你把这件"最简单的事"记录下来。

RFC 写一堆想法让人来拷打(

设计文档的具体写作#

在真正动手写代码之前,工程师通常会先写一份非正式的文档,用来描述这套系统或应用的设计思路。它记录的是高层次的实现策略,以及背后那些关键的设计权衡,重点放在需要做取舍的地方。

写作的过程本身,会促使作者在动手编码前就把那些原本模糊的问题想清楚。而这份文档一旦写成,又能确保所有相关的人和团队都认可这套设计。同时,它也充当了一座桥梁,把系统当下的样貌和未来可能演进的方向连接起来,让后来者能顺着它理解一段历史。

一份设计文档里通常有什么#

上下文与范围(Context and scope)。这一节要给读者一个大致的印象:这个系统是被造出来的,它所处的环境是什么样的,又要解决什么。这里说的是现状与约束,而不是需求。它应该尽量简短、客观——因为读者往往对项目背景已经有所了解,只是需要一个快速的复习,以及一份可以引用的信息源。

目标与非目标(Goals and non-goals)。用一个简短的清单列出系统的目标。有时候更有用的,是同时列出那些明确不在目标之内的事情——注意,非目标不是"负目标"(比如"系统不能崩溃"),而是那些本来看起来合理、值得做,但你有意选择不做的事情(比如"不追求强一致性")。

真正的设计(The actual design)

设计这部分,恰恰是最难给出通用建议的地方——就像那张"如何画猫头鹰"的经典梗图:第一步画两个圆,第二步"画出剩下的猫头鹰"。真正的困难和创造性,都藏在那个语焉不详的"第二步"里。

不同的项目,这一节的样貌千差万别。但有几条通用的原则是成立的:你的写作对象是读者,而不是自己,所以要照顾读者能理解的程度;要聚焦在权衡与取舍上,而不是罗列所有细节;要诚实地面对那些还没想清楚、或者可能出错的地方。下面几个小节,是这一节里经常出现的元素。

系统上下文图(System-context-diagram)。很多文档里,一张系统上下文图是极其有价值的。它把你要造的系统放在它所处的更大生态里,展示出这个系统和周边其他系统之间的关系与边界。

系统上下文图示例:展示目标系统与其上下游系统之间的依赖与数据流关系的方框
系统上下文图示例:展示目标系统与其上下游系统之间的依赖与数据流关系的方框

这类图往往用方框和箭头就能画出来。关键是,它展示的是系统与外部世界的边界,而不是系统内部的模块划分。

API。如果你正在设计的系统对外暴露 API,那么把这些接口的样子勾勒出来通常是值得的。但要克制:不要把完整的接口定义原样贴进来,因为那些内容通常可以用代码本身来表达,而且很容易过时。真正该写进文档的,是为什么这样设计接口,以及这些设计如何影响使用者。

数据存储(Data storage)。如果系统要存储数据,同样值得聊聊你打算怎么存、用什么形式存。这里的原则和 API 一样:不要贴出完整的 schema 定义,而要讲清楚背后的取舍——为什么选这种存储、这种数据模型,它带来了什么代价。

代码与伪代码(Code and pseudo-code)。设计文档里一般应该避免贴大段代码或伪代码。只有当你要展示某个新颖的算法,或者某段代码本身就是设计的核心创新时,贴一小段才有意义。

约束的程度(Degree of constraint)。设计文档的一个重要维度,是它给后续实现留出了多大的自由度。这跨越了一个很宽的光谱:一端是"绿地"项目(greenfield)——从零开始,几乎没有任何约束,你可以自由发挥;另一端则是那种约束极强的系统——它要接入一个成熟庞大的既有体系,你的设计空间被压缩得很小,大量决策其实早已被现状锁定。有意思的是,后者往往比前者更难设计,因为你要在密密麻麻的约束缝隙里找出一条可行的路。这两类项目的设计文档,写法和侧重点都会很不一样。

备选方案(Alternatives considered)#

这一节列出你认真考虑过、但最终没有采用的其他设计方案,并说明它们各自的优劣,以及你为什么最后选了现在这个方案。

在很多设计文档里,这往往是最重要的一节。它最能体现出你确实做过扎实的权衡,考虑过多种可能性,而不是撞上第一个能用的方案就一头扎进去。它也让评审者能够顺着你的思路,判断你的取舍是否合理——甚至提出一个你没想到的、更好的选项。

横切关注点(Cross-cutting concerns)#

几乎每个组织都有一些贯穿所有系统的关注点,比如安全、隐私、日志、国际化、合规等等。这些议题通常有专门的团队和专家在把关。

在设计文档里专门开一节,说明你的设计如何影响这些横切关注点,又是如何应对它们的,是一种很好的实践。这样做,一方面强迫作者真正去思考这些问题——而不是等到系统上线才追悔莫及;另一方面,也给了相关领域的专家一个入口,让他们能够审视你的设计,及早发现隐患。这些议题的关键在于:它们几乎不可能在事后被廉价地补上,越晚处理代价越高。

设计文档应该多长#

一份设计文档的篇幅,某种程度上反映了它所描述系统的复杂度。

大型项目往往要一份10 到 20 页的文档,足够长,能覆盖真正重要的设计决策;又足够短,能让人真的坐下来读完。如果你发现自己写出了一份远超这个长度的文档——比如几十上百页的"巨型设计文档",那通常是个信号:也许这个问题的范围还没有被拆解到足够小,应该考虑把它切分成几个可以独立解决的子问题,分别成文。

另一端,对于那些改动不大、但仍然值得记录的决策,可以写一份1 到 3 页的迷你设计文档(mini design doc)。它保留了设计文档的核心价值——逼你把问题想清楚、让相关的人达成共识——但省去了大部头文档的仪式感和重量。迷你文档在敏捷、快速迭代的团队里尤其常见。

设计文档的生命周期#

一份设计文档会经历几个相对固定的阶段。

创建与快速迭代(Creation and rapid iteration)。文档的第一版,通常由一位或几位作者快速写就。在这个阶段,它常常还很粗糙,充满了不确定和待填的空白。作者一般要在这时和多人来快速地迭代打磨,补上遗漏的部分、推翻不成立的假设。这是文档变化最剧烈的时期。

评审(Review)。当文档稳定下来,就进入更广泛的评审阶段。这时它会被分享给更大范围的相关方——包括各个横切关注点的专家、会受这套设计影响的其他团队,以及资深的工程师。评审可以以多种形式进行:文档内的评论、面对面的设计评审会议,或者两者结合。评审的目标,是让这套设计尽可能多地经受住不同视角的检验,在动手写代码之前把问题暴露出来。

实现与迭代(Implementation and iteration)。设计被认可后,团队开始按照它来实现系统。在真正动手的过程中,几乎必然会冒出一些当初没预料到的问题。这时,原来的设计需要相应地调整。一个健康的做法是:让文档跟着这些重大的、非预期的偏离一起更新——至少要把那些偏离设计的关键决策记录下来。

维护与学习(Maintenance and learning)。系统上线并运行一段时间后,现实会告诉你当初的设计哪些成立、哪些不成立。这时,回到当初的设计文档,把实际结果和当初的预期对照一下,是极有价值的学习机会。这不仅让作者本人成长,也让整个组织在下一次面对类似问题时,能做出更好的判断。设计文档,由此成为组织长期记忆的一部分。

ED#

设计文档记录的是高层次的实现策略,以及背后那些关键的设计权衡,重点放在需要做取舍的地方。写作的过程本身,会促使作者在动手编码前就把那些原本模糊的问题想清楚。而这份文档一旦写成,又能确保所有相关的人和团队都认可这套设计,它也充当了一座桥梁,把系统当下的样貌和未来可能演进的方向连接起来,让后来者能顺着它理解一段历史,减少沟通对齐的成本。

可能会有人想:如今大模型已经能帮我们生成代码、补全接口、甚至起草文档的初稿,那认认真真写设计文档这件事,是不是正在变得过时?

个人觉得恰恰相反。在 AI 时代,写文档反而更重要了。AI 让 "写代码" 这一环的成本急剧下降,反而把真正稀缺的东西凸显了出来 —— 清晰地想清楚要做什么、为什么这么做,以及在众多可能性中如何取舍。这正是设计文档从头到尾在训练的能力。当生成一段实现只需要几秒钟,决定 "该不该实现它、该以什么形态实现" 的判断力就成了工程师最核心的价值所在。

从更实际的层面看,AI 也让文档写作的意义发生了双向的加强。一方面,大模型可以承担初稿、润色、查漏这些机械的部分,把作者从 "憋字数" 里解放出来,让人能把精力集中在把设计中的权衡讲透、把备选方案比清楚、把风险摊开来。另一方面,一份结构清晰、意图明确的设计文档,本身就是喂给 AI 的最好的上下文: 把目标、约束和边界写明白,AI 实现时就越不容易跑偏。所以会写文档的人,往往也更会用 AI

更根本的一点是,设计文档承载了判断、共识与记忆。AI 能生成看似合理的文字,但它无法替你和团队达成真正的认同,无法替一个组织沉淀出 "我们当初为什么这样选" 的集体记忆,也无法替你承担一个决策错了之后的代价。

工具在变,但把一件复杂的事情想清楚、说明白、并让别人信服,我觉得这项能力很难过时。

分享到社交平台

将本文分享给你的朋友们

2026-07-20-技术写作-关于设计文档
https://zhongye1.github.io/posts/2026/2026-07-20-关于技术写作-设计文档/
作者
Zhongye
发布于
2026-07-20
版权声明
CC BY-NC-SA 4.0

评论

Profile Image of the Author
Zhongye
南漂中
公告
新的博客站!旧站点传送门 👇
音乐
专辑封面

音乐

暂无播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章数
147
分类数
14
标签数
209
总字数
445,674
运行天数
0
最后更新
0 天前
总访问量
42296
访客数
29212

目录