一、软件设计文档的目的
对于我和我的团队而言,软件设计文档旨在:
- 明确思路:梳理问题、目标与解决方案,识别风险,做到胸有成竹。
- 识别依赖:提前确定外部依赖,与利益相关方达成共识。
- 促进沟通:便于团队成员理解设计,参与评估与讨论,集思广益。
- 任务拆解:确保任务分配明确,团队协同工作,共同达成单个成员难以完成的任务
你可以从上面这些目标中发现,对我的团队而言,软件设计文档开发前的意义,比维护阶段 的意义大,尽管他对维护阶段带来的帮助也不小。
对于软件工程师而言,是否能够写好一个软件设计文档,决定能否将自己的工程影响力扩展 到个人产出之外。如果你编写了一个设计,让你和其他三位工程师能够协同工作,那么你的 工程产出就变成了“我协调了一个团队,共同构建了一个我们中任何一个人都无法单独完成 的东西。
基于此,实践中,我形成了软件设计文档的八股文。
二、软件设计文档的八股文
1. 背景、目标和约束条件
开篇明义,介绍这个软件设计的背景,明确要解决的核心问题。
列出所有的约束条件。比如某些新功能的重构,约束条件就是要兼容老的接口。
时间限制也是约束条件。
2. 设计遵循的原则
明确设计应当遵循的指导原则,这些原则可能涉及用户体验、性能优化、安全性、可扩展性等方面。
这些原则应明确在遭遇冲突时,优先级的考量。例如,有时性能优化为首要任务,而其他情况下,灵活性 和可扩展性则被视为更为重要。
通过阐述这些原则,文档不仅展示了设计的价值取向,也为团队成员提供了决策时的参考框架。
3. 系统架构
详细描述系统的整体结构,包括层次划分、模块间关系、数据流向等。使用图表、UML图等工具,直观展示系统 的骨架,帮助读者快速把握全局。
通常,这里会有一张high level的系统架构图,简要描述如下: 1) 图中展示了各个模块及其运行态关系,如哪些模块作为库集成到其他模块中,哪些作为独立进程(daemon)运行。
2)结合图说明模块分工: 明确每个模块的基本职责,突出显示新增或变更模块的具体职责
3)图中体现出进程间通信机制: 对于独立运行的模块,说明其使用的IPC通信机制或接口;区分是基于依赖关系的 直接接口调用,还是基于契约解耦的依赖(如ROS2)
以下是系统架构图示例
4. 系统提供的功能、接口和编程模型
将本模块/系统作为一个黑盒,以图例的方式展示本模块/系统的编程模型。 提供本模块/系统变更的对外接口明确定义。
以下是编程模型图例示例
到4这里,同外部模块的依赖以及交互关系就确定了,文档已足以同外部团队、利益相关方讨论。
5. 系统内模块划分
从这个部分开始,我们开始关注具体实现(前面主要是功能和职责)。 这部分我们在实践中,有三个出发点,一是软件设计者通过这个部分的思考更好地对软件、模块、功能进行抽象,是一个反复论证、迭代 自己方案的过程,有风险也能够充分识别,二是团队内部通过这部分,能够很清晰地get到软件设计者的思路,从而可以提供更加有建设性 的建议,三是可以根据需要对工作进行分工。
系统内模块划分一般可以有一张图,这张图本质上和3中的系统架构图类似,区别在于这个时候我们讲自己的模块作为一个系统,对内部进行 更细粒度的模块划分。同样,模块间的接口也类似。
这部分应该尝试把关键类的接口明确。
6. 核心数据结构设计
详细描述系统中的核心数据结构,包括数据库表结构、对象模型、数据传输对象等。清晰的数据设计有助于确保数据的准确性和一致性。
这部分涉及到领域业务模型的实现,设计人员通过这部分的反复思考,能够不断优化自己的业务设计。
7. 典型场景交互图
类似Use cases
通过绘制典型场景下的用户交互流程图和系统内部处理流程图,直观展示系统的运行逻辑。这有助于其它人理解设计。
8. 核心算法实现
tomorrow.cyz@gmail.com