2. 文档编写核心原则:文档的目的、受众分析、可追溯性原则

好,咱们进入正题。文档到底为什么而写?这个问题我问过很多工程师,答案五花八门。有人说是为了应付审核,有人说是为了交接,还有人说是为了证明自己干过活。嗯,这些都对,但都不全对。

我个人习惯把文档看作「沟通的桥梁」。你想想看,一个项目少则三五人,多则几十上百人。每个人脑子里的想法都不一样。没有文档,全靠口头传话,最后肯定乱套。所以,文档的核心目的就三个:记录决策、传递信息、支撑验证

核心观点:文档不是写给审核员看的,是写给未来的自己看的。三个月后你回头翻代码,如果没有文档,你大概率会问自己:「这谁写的?这写的什么鬼?」——嗯,那个人就是你自己。

2.1 文档的目的:你到底想解决什么问题?

写文档之前,先问自己三个问题:

  • 这份文档给谁看?——决定了语言风格和技术深度。
  • 他们想从中得到什么?——决定了内容重点。
  • 看完之后他们需要做什么?——决定了文档的交付物和格式。

我在项目中遇到过一件事:有个同事写了一份软件需求规格说明,洋洋洒洒五十页。结果评审的时候,测试工程师说看不懂,开发工程师说太啰嗦,项目经理说找不到关键信息。为什么?因为他没搞清楚文档的目的。测试想看的是验收标准,开发想看的是功能逻辑,项目经理想看的是进度和风险。一份文档想满足所有人,最后谁都满足不了。

所以,我建议你写文档前先画个「目的-受众-产出」的三角图。比如:

文档类型 核心目的 主要受众 关键产出
系统需求规格 明确客户需求 客户、项目经理 需求列表、验收标准
软件架构设计 定义模块划分 开发工程师 架构图、接口定义
单元测试报告 验证代码正确性 测试工程师、评审员 测试用例、覆盖率、缺陷列表
集成测试计划 规划测试策略 测试团队、项目经理 测试范围、时间表、资源需求

小技巧:写文档前,先写一句话的「文档声明」。比如:「本文档旨在定义ABS控制模块的软件需求,供开发团队进行详细设计使用,测试团队可据此编写测试用例。」——这句话写清楚了,后面就不会跑偏。

2.2 受众分析:别用你的专业去折磨别人

这一点我感触特别深。很多工程师写文档,默认读者跟自己一样懂技术。结果呢?满篇的专业术语、缩写、内部代号。你想想看,一个刚入职的新人拿到这份文档,他是什么感受?

我有个习惯:写文档前先给受众「画像」。比如:

  • 客户:不懂技术细节,只关心功能、性能、成本、时间。
  • 项目经理:关注进度、风险、资源、依赖关系。
  • 开发工程师:需要接口定义、算法逻辑、数据结构。
  • 测试工程师:需要输入输出、边界条件、异常处理。
  • 审核员/评估员:关注流程合规性、可追溯性、证据完整性。

我曾经给一个客户写系统需求文档,用了很多「ECU」「CAN」「LIN」「UDS」这些缩写。客户看完后问我:「ECU是什么?是发动机控制单元吗?还是电子控制单元?」——你看,同一个缩写在不同语境下意思完全不同。从那以后,我写文档第一页一定会加一个「术语表」。

避坑指南:我曾经见过一个项目,开发团队写的设计文档里全是「该模块」「该接口」「该函数」。评审的时候,大家争论了半天才发现,每个人理解的「该模块」根本不是同一个东西。所以,写文档时一定要明确指代,别用「该」「其」「它」这种模糊词。

说白了,受众分析就是「换位思考」。你写文档的时候,把自己想象成读者。你希望看到什么?你希望怎么呈现?你希望多详细?——想清楚这些,文档质量至少提升一半。

2.3 可追溯性原则:别让你的文档变成孤岛

可追溯性,这是ASPICE里特别强调的一点。什么意思呢?就是从需求到设计,从设计到实现,从实现到测试,每一步都要能「追」回去

我举个例子。假设客户提了一个需求:「车速超过120km/h时,仪表盘显示红色警告。」那么:

  1. 系统需求文档里要有一条:SYS-REQ-001 车速超120km/h报警。
  2. 软件需求文档里要对应:SW-REQ-001 读取车速信号,判断是否超过阈值。
  3. 设计文档里要体现:模块A负责车速计算,模块B负责报警显示。
  4. 测试用例里要验证:TC-001 输入车速121km/h,检查仪表盘是否显示红色。

你看,从SYS-REQ-001到SW-REQ-001,再到设计模块,再到测试用例,这是一条完整的链条。任何一个环节断了,审核的时候就会问:「这个需求怎么实现的?测试覆盖了吗?」

我个人习惯用需求编号+层级编号的方式来管理可追溯性。比如:

// 需求编号示例
SYS-REQ-001: 车速超120km/h报警
    SW-REQ-001.1: 读取车速信号(周期100ms)
    SW-REQ-001.2: 判断车速是否大于120km/h
    SW-REQ-001.3: 触发报警显示
        SW-DES-001.3.1: 模块A提供车速接口
        SW-DES-001.3.2: 模块B调用报警接口
            SW-TC-001.3.1: 输入车速121km/h,验证报警显示
            SW-TC-001.3.2: 输入车速119km/h,验证无报警

这样,评审的时候一眼就能看出:需求有没有被实现?实现有没有被测试?测试有没有覆盖所有分支?

重要提醒:可追溯性不是「为了追溯而追溯」。它的本质是变更影响分析。比如客户突然说:「车速阈值改成130km/h。」如果你有完整的追溯链,你就能快速定位:哪些需求要改?哪些设计要改?哪些代码要改?哪些测试要重跑?——没有追溯性,你只能靠脑子记,或者全盘重来。

嗯,这里要注意一点:可追溯性不是「越多越好」。我见过有些团队,每个需求都追溯到了代码行级别。结果呢?需求一变更,追溯表改得想哭。我建议追溯粒度控制在「功能模块」级别,不要追到具体代码行。代码行级别的追溯,那是静态分析工具干的事,不是文档该干的。

2.4 三个原则的融合:一个实际案例

最后,我分享一个实际案例。之前我做的一个ADAS项目,客户要求写一份「车道保持辅助系统」的软件需求文档。

第一步:明确目的
这份文档的目的是:定义LKA系统的软件功能需求,供开发团队进行详细设计,供测试团队编写测试用例。

第二步:分析受众
主要受众是开发工程师和测试工程师。开发需要知道:输入信号有哪些?算法逻辑是什么?输出信号怎么定义?测试需要知道:正常场景怎么测?异常场景怎么测?边界条件是什么?

第三步:建立追溯
我用了三层追溯:

  • 第一层:客户需求 → 系统需求(用SYS-REQ编号)
  • 第二层:系统需求 → 软件需求(用SW-REQ编号,并注明对应SYS-REQ)
  • 第三层:软件需求 → 测试用例(用TC编号,并注明对应SW-REQ)

结果呢?项目进行到一半,客户要求增加「弯道限速」功能。我打开追溯表,发现受影响的需求有3条,设计模块有2个,测试用例有5个。我花了半天时间就完成了变更影响分析。而另一个没有做追溯的模块,团队花了三天才理清楚。

我的建议:可追溯性不是一次性工作,而是持续维护的过程。每次需求变更、设计修改、测试补充,都要同步更新追溯表。别等到审核前再补,那时候补出来的追溯表,连你自己都不信。

好了,这一章的内容就到这里。记住三句话:文档要有目的,别写废话;文档要有受众,别自说自话;文档要有追溯,别变成孤岛。下一章我们聊聊「文档结构设计:如何让读者一眼找到关键信息」。