
如何写一份牛X的汽车软件需求
坦白而言,说需求工程师是一个项目最重要的职位也不为过。一份准确、清晰的需求文档是一个优秀项目的基石,而一个优秀的需求工程师团队更能够直接大幅提升整个项目的效率,甚至能引导整个项目组以最优的路径开发。需求工程师本来应该是由经验丰富的老工程师担任的。
很可惜,绝大多数车企都没有对员工进行过系统的需求撰写培训,往往是新员工们照着前人留下的模板依葫芦画瓢,不得要领。
虽然大部分软件开发人员都不会成为专职的需求工程师,但对软件需求“读、评、测、改”几乎是每位汽车行业软件工程师的日常。如果能够站在需求工程师的角度看问题,那么平时与需求打交道也会更加得心应手。
一份好的软件需求,就像一盘干锅牛蛙,远观而赏心悦目、食欲大增,细尝则色味俱全、营养丰富。牛蛙尽是精华没有杂肉,又辅以葱椒花生,调节口感、丰富层次。那么什么样的需求文档才可以当此美喻?
我认为,好的软件需求要符合以下六个条件。我将试着通过一个例子来逐条讲解。
1、干净利落
软件需求只写必要信息,只能包含描述性、定义性的内容,而不能包含解释性的内容。需求内容可以用不同字体表示不同含义,使整体阅读起来干净、清晰、有序。
这里举一个我前面文章里用过的例子:
The signal ACC Active State shall be set to SUPPRESSED if the following conditions are fulfilled[ACC-Req 002]:
- Safe Vehicle Speed is less than 30kph OR
- Safe Vehicle Speed is greater than 120kph.
这段需求中的“shall”、“set to”、“if...fulfilled”都是定义性的用词,不拖泥带水,用最简单的语句描述完软件行为。很多新手写需求时会带上学生时代写作文的拖沓毛病,写成这样:
The signal ACC Active State shall [ ***always*** ] be set to SUPPRESSED if [ **all of** ] the following conditions are fulfilled
注意方括号里的部分,完全就是废话,并且容易引发歧义。这种内容是要尽量避免在需求文档中出现的。
另外,这段需求中出现了斜体,代表“信号”,出现了大写黑体,代表“状态”。很多需求里不会出现“30”、“120”这种具体的数字,因为这是标定数据,以后会改的,那么就可以用大写加下划线比如 “MIN_ACC_ACT_SPD”、“MAX_ACC_ACT_SPD”的形式来代替,说明这是可标定数据。这些格式的变化可以显著地提升需求文档的可阅读性以及阅读效率。
干净利落
2、简单明确
写软件需求时不能使用有二义性的语句或词组,不能使用带主观色彩的词语。另外,尽量定义软件在什么情况下“做什么”,而不是定义在什么情况下“不做什么”,因为前者更简单完备,不容易有遗漏。
就着前面的例子。
The signal ACC Active State shall be set to DEACTIVATED if [ ***each of ***] the following conditions are fulfilled[ACC-Req 002]:
- Camera Status is invalid,
- Radar Status is invalid .
方括号里的 "each of" 就是引入二义性的用词。你告诉我读完这条需求以后,你觉得前述两个条件彼此是“与”的关系,还是“或”的关系?
如果你英语像我一样好(大雾),那么这里 each of 是指“与”的关系,也就是说只有雷达和摄像头都失效了,ACC才会退出。如果想指“或”的关系,行文应该用 "either of" 。但是相信我,就算你给一个英国人看,大部分英国工程师也弄不清楚。所以这种产生歧义的词是不能用的。
正确的写法是删去 each of, 并明确的写出关系词 or , 来消除二义性:
The signal ACC Active State shall be set to DEACTIVATED if the following conditions are fulfilled[ACC-Req 002]:
- Camera Status is invalid,OR
- Radar Status is invalid .
偶尔也有萌新会写成这样:
The signal ACC Active State shall be set to DEACTIVATED if the following conditions are fulfilled[ACC-Req 002]:
- Safe Vehicle Speed is [***less enough***], OR
- Safe Vehicle Speed is [***too fast***].
“如果车速足够慢就退出ACC”,“如果车速太快了就退出ACC”。别笑,这个例子可能有些极端,没有十年的脑血栓估计写不出来。但是真的经常有人用一些主观的、完全没有明确定义的概念来描述软件需求,这也是要避免的。
最后,不要把需求按照否定定义去写。比如不要把上面这个需求写成这样:
The signal ACC Active State shall [***NOT***] be set to DEACTIVATED if the following conditions are fulfilled[ACC-Req 002]:
- Camera Status is valid,OR
- Radar Status is valid .
"只要雷达或者摄像头有一个可用,ACC就不退出"。不要写这种否定型的需求,因为不光读起来费劲,还很容易遗漏一些情况。
简单明确
3、不可分解
每条需求都必须是组成某个功能的最基本单元,不能够再继续分解。
The signal ACC Active State shall be set to SUPPRESSED if the following conditions are fulfilled[ACC-Req 002]:
- Safe Vehicle Speed is less than 30kph OR
- Safe Vehicle Speed is greater than 120kph.
大家仔细看我用的这个例子。它其实不能被认定成一条需求,因为如果你仔细分析,这段话是可以分解的。我可以用以下两条需求来完全替代它:
- The signal ACC Active State shall be set to SUPPRESSED if Safe Vehicle Speed is less than 30kph.
- The signal ACC Active State shall be set to SUPPRESSED if Safe Vehicle Speed is greater than 120kph.
所以我们虽然在行文上可以把这段描述写成一段话,但必须赋予它两个需求编码requirement number,每个条件一个。只赋予一个编码是错误的,并且会在测试和链接的时候出现问题。
不可分解
4、便于测试
每条需求都必须能够直接测试。这里“直接”的意思是需求里描述的信号I/O接口是完备的,是测试设备可以直接控制或者读取的。又来:
The signal ACC Active State shall be set to SUPPRESSED if Safe Vehicle Speed is less than 30kph.
这条需求写明了软件输入信号是Safe Vehicle Speed, 输出信号是 ACC Active State。只有在测试人员(软件需求对应的是HIL测试)能够改变输入信号、观察输出信号的情况下,这条需求才是合理的。
这个例子里Safe Vehicle Speed 可以通过改变CAN bus上的车速信号改变,并且能通过XCP观察,输出信号是一个CAN信号可以直接观察,于是这才是一条好的需求。如果信号不能直接观察,就要改变需求的描述方式。这就是为什么HIL测试工程师一定要参与需求评审。
还有一种情况是需求内容根本无法测试。例如最好不要在软件需求里写PI控制器的详细控制特性,因为很多情况下HIL测试是不容易设计出测试用例的。这部分需求最好写到软件需求的下一级,也就是设计需求中,用SIL的方式测试。
便于测试
5、可溯源性
所有的软件需求向上必须要连接一条系统需求,向下必须链接一条设计需求。平级必须链接一条HIL测试用例。这就不多说了。
一个值得注意的点是,一些具有安全等级ASIL的系统需求,会分解降级为若干个低等级软件需求。我经常在项目中看到某个需求后面标着 “B(D)”, 但是既不知道这是哪个ASIL D需求分解来的,也不知道分解出的另外一个 “B(D)” 需求死哪去了,最后不了了之,这是应该极力避免的。
有安全等级的需求要格外注意连接到它的上级安全需求中去。
溯源连丝
6、正确区分“需求”和“信息”
做到前面这些要求,还不足以写出一份完美的需求文档。好的需求文档除了定义软件行为,还要有充足的解释性内容,帮助阅读者理解软件行为,做到仅看文档就能知其然、知其所以然。这就是需求文档的“信息information“部分。
前面说了,需求requirements 只能包含描述性、定义性的内容,所以除了这部分以外,所有的其他内容都属于信息。信息主要分成三类:
- 解释软件行为的原因,举例子、作类比,补充材料帮助读者理解
- 重复定义的软件行为。为了解释行为A,把其他需求文档中的相关软件行为B再复述一遍。由于行为B已经作为需求在别处出现过了,它的复述虽然是定义性语言,但也只能作为信息。
- 需求作者给HIL测试团队留下的建议。很多时候HIL测试是外包团队进行,他们对软件接口并不一定充分熟悉。有时软件需求的作者会在需求文档中写下一些备注,指导HIL团队找到正确的接口。
前面的例子中,我提到了ACC的状态“SUPPRESSED”。好的需求文档在正式定义这些状态之前,一定要先写一段描述性信息,以较平易的语言告诉读者都定义了哪些状态、为什么定义这些状态。各个状态之间,比如SUPPRESSED 和 DEACTIVATED都是退出ACC,它们有什么区别。最后给出状态转移图,做了这些之后再开始正儿八经的严格定义。
文章转载自公众号:汽车电子与软件
