01.
惯性
开始推行软件质量体系的转型之时,落地最大的阻力便是“惯性”——按之前习惯的做法已经实施了多年也没出大问题的项目,凭什么要按新的方法来操作?需要额外工作量不说,还有可能引入不可知的风险,还不如照老方法做的安全。体现在具体工程实践中,最典型的例子便是系统需求与软件需求的分离了,一般的展开是这样的:
质量工程师:软件需求文档一篇都还没有,啥时候能好?
软件工程师:系统需求文档已经详细到可以写代码了,重写一份软件需求不是多此一举?
质量工程师:根据流程定义,需求文档需要分层,这样逻辑清晰职责也明确。
系统工程师:这样一来我们的系统需求也得改,还有评审、追溯……都是工作量啊
软件工程师:好吧,我们把系统需求抄一份过来作为软件需求一对一链接,这样大家都好交差……
质量工程师:额……
于是乎,“软件定义汽车”的口号喊了些许年,时至今日的状态,依旧是“软件依附系统,系统定义汽车”。不同于刚入局汽车行业的新势力,传统的OEM和Tire 1/2/3原本就有深厚的技术积累,体现在需求文档中,就是系统需求事无巨细通通包揽直接从客户需求打通到产品代码,而后继项目的不断重用之下又强化了这样的系统需求文档。
类似于被戏称为“屎山”的“祖传代码”,把详细的系统需求拆分可是牵一发而动全身的事情,谁也不想吃力不讨好地为了优化架构而分拆系统需求——万一改出了问题这锅谁背。这样一来,哪怕有了全新的项目全新的需求,习惯的力量积重难返,仍然是基于一坨面面俱到的系统需求进行开发,始终看不到软件团队强势崛起的那一天,而是始终依附于系统部门亦步亦趋地修改系统需求中设计软件的部分,温水煮青蛙,一日复一日,直到结束的那一天就结束了。
而如若不想原地踏步而期待有所改变,比起一昧吐槽,还是就事论事地分析系统需求和软件需求的区分与联系,给出建议方案,然后才能决定入手策略、影响范围、拆分准则的细节,继而推断出所需的资源去实施转型。下面用“5W1H”的方式看看两者的区别——
Why(目的)
如前一篇提到,汽车软件开发的开发生命周期不同于纯软件开发的SDLC(软件开发生命周期SDLC - Software Development Life Cycle),是属于复杂度更高的ALM(应用程序生命周期管理ALM - Application lifecycle management)。为了应对ALM的复杂性,在顶层设计中进行分层非常关键,因而在汽车软件开发流程中,德国汽车工业联合会VDA给出方案之一则是“插件(Plug-in)”的概念,在ASPICE的标准中把产品分解为不同的级别(Layer),系统级别提纲挈领,而软件、机械、硬件(电子)各司其职。
诚然,对既有需求进行分层会导致额外工作量并引入不确定风险,但如果不动这个手术,目前的需求文档已经是隐患重重了就等着那一天爆发,以下列举几个:
1)权责不清:由于系统和软件团队共通维护一篇需求文档,到底哪块归系统哪块归软件哪块又归属其他部门(例如EE、ME)很难清楚划分,尤其在文档越来越臃肿的情况下问题日渐凸显。如果导致了产品缺陷,根因追溯下来到底算谁的时候如何预防又是一笔糊涂账。恶性循环下来,产品缺陷终将积重难返,等到重大缺陷的时候再想回头对源头的需求文档动手术的时候,发现还得分层……那么,早干嘛去了?
2)细节失控:汽车电子产品的复杂度随着几何级数增加,之前的系统工程师或许可以做到提供从客户需求到详细设计的“一站式服务”,随便问某个诊断码是用01还是用02都能脱口而出,但人员是实时流动的、程序是日渐复杂的,稍有变化在具体细节上就会失控,万一人员离职了细节没交接到、万一通信协议定义或者算法更新了两个部门没有同步……那造成的后果可能是灾难性的。
3)影响范围:系统需求向上面向客户类似于产品经理、软件需求面向代码类似于程序员,两个部门立场与技术背景都不同的团体共同维护一篇文档,当变更发生或问题修正时需要进行影响性分析(Impact Analysis)的时候会发现,在这篇已经臃肿不堪的文档中已经找不到清晰的脉络进行全方位覆盖的影响分析了,其后果就是每一次的变化都可能为下一次缺陷的爆发埋下隐患。
……
在ASPICE中,为了对需求进行分层,系统需求归属SYS.2、软件需求归属SWE.1,两者分在了不同的过程域中(如图)——
过程ID | SYS.2 | SWE.1 |
过程名称 | 系统需求分析 | 软件需求分析 |
过程目的 | 系统需求分析过程的目的是:将已定义的利益相关方需求转换成一组系统需求,以指导系统设计。 | 软件需求分析过程的目的是:将系统需求中与软件相关的部分转化为一组软件需求。 |
过程成果 | 成功实施这个过程的结果如下: | 成功实施这个过程的结果如下: |
1) 建立了一组定义的系统需求 ; | 1) 定义了系统中分配给软件要素的软件需求及其接口; | |
2) 对系统需求进行分类,并分析了其正确性和可验证性; | 2) 将软件需求进行分类,并分析了其正确性和可验证性; | |
3) 分析了系统需求对运行环境的影响; | 3) 分析了软件需求对运行环境的影响; | |
4) 定义了系统需求实施的优先级; | 4) 定义了软件需求实现的优先级; | |
5) 根据需要更新了系统需求; | 5) 根据需要更新了软件需求; | |
6) 建立了利益相关方需求和系统需求之间的一致性和双向可追溯性; | 6) 在系统需求与软件需求之间、在系统架构设计与软件需求之间建立了一致性和双向可追溯性; | |
7) 从成本、进度和技术影响来评估系统需求; | 7) 从成本、进度和技术影响来评估软件需求; | |
8) 约定了系统需求,并与所有受影响方沟通。 | 8) 约定了软件需求,并与所有受影响方沟通。 |
从两者的过程目的中可以清晰的看到上下游关系,即SYS.2中“系统需求中与软件相关的部分”就是SWE.1的输入,而两者各自的8个过程结果也是承上启下的一一对应,最大的不同便是工作产品对象的不同,一个是系统需求,一个是软件需求,这也是接下来要讨论的“What(对象)”部分。
02.
分层
流程体系的部署总有许多地方需要平衡,以团队管理为例,如果在5-6人的团队中进行分层管理,不单无益于提升效率反而会增加内耗;相似的,在需求管理的场景,如果只有5-6页由同一个人维护的需求,为了分层而拆分成两篇文档分开维护,也会带来不必要的浪费。即便在行业标准的ASPICE中定义的分层,在实际的项目落地也是有一定的灵活性的。
以下是ASPICE3.1标准中对于“双向可追溯性和一致性”的图例,从SYS.1的利益相关方需求(Stakeholder Requirements)到SYS.2的系统需求(System Requirements),然后从SYS.2的系统需求(System Requirements)再到SWE.1的软件需求(Software Requirements),是一个自上而下的关系。
然而在现实的项目中,来自客户的需求很可能是包含了具体的技术细节甚至参数定义逻辑判定的内容,这时如果为了满足流程,在系统需求和软件需求重复的拷贝相同的内容就变得毫无意义了。更务实的做法是应当直接把客户需求直接链接到软件需求,而为了确保追溯性的全覆盖再把下游的细化软件需求链接到上游更概要的系统需求中。
相对于纯理论的介绍放在实际的场景中进行分析会更加容易理解,这里就以AEB(主动刹车)功能为例看看需求的分层。
客户需求1 | 采用雷达和摄像头测出与前车或者其他障碍物的距离,系统控制模块将测出的距离与警报距离、安全距离进行比较,小于警报距离时就进行警报提示,而小于安全距离时,AEB制动会启动,使汽车刹停。 |
系统需求1 | 在80米距离识别车辆(Truck, Car, Bus),在40米距离识别行人,自行车,摩托车……满足条件时唤醒AEB功能。 |
软件需求1 | AEB功能模块A在满足如下条件时唤醒: - 物体距离 <= 距离条件阈值 - 同一车道判定 == TRUE…… |
在以上的例子里,客户需求、系统需求、软件需求这三者是满足自上而下的清晰脉络的,可以进行直接关联。而当客户需求本身已经包含了技术细节时,情况可能会有所不同,可以看看如下场景。
客户需求2 | 预填充(Prefill)应在满足以下条件时激活 - 行驶速度 <= 速度条件阈值 |
软件需求2 | 预填充(Pre-fill)应在满足以下条件时激活 - 行驶速度 <= 速度条件阈值…… |
系统需求2 | 紧急制动AEB包含了以下子功能:前碰警报FCW、短促制动Acute warning、预填充Prefill、制动辅助EBA、紧急制动AEB。 |
客户需求1 | 采用雷达和摄像头测出与前车或者其他障碍物的距离,系统控制模块将测出的距离与警报距离、安全距离进行比较,小于警报距离时就进行警报提示,而小于安全距离时,AEB制动会启动,使汽车刹停。 |
这里“客户需求2”里,对预填充(Prefill)的激活条件已经细化到了软件层面的具体实现,并且给出了变量名和阈值,可以直接作为软件需求的条目使用,因而可以直接链接到“软件需求2”,甚至直接拷贝就能使用作为下游的详细设计输入。而此处,如果单纯地直接从SYS.1链接到SWE.1会导致SYS.2的追溯缺失,为了确保需求的追溯性,“软件需求2”可以链接到“系统需求2”包含了预填充(Prefill)这一内容概要介绍的需求条目中,而“系统需求2”又可以链接到“客户需求1”中客户对整体AEB功能的要求概述里。以上例子画图表示便是:
因此,为满足产品功能,实现100%功能覆盖的追溯性是不可妥协的,而实现手段上需要考虑现实情况,需求文档的体量很小如前面说的只有5-6页由同一个人维护的需求文档,其中系统需求和软件需求完全可以在同一篇文档里维护,不过放在不同的章节里罢了,并借助需求管理工具可以将其中的WI(Work Item工作项)进行链接追溯。
下面列举SYS.2-系统需求分析和SWE.1-软件需求分析这两个过程域的输出工作产品,可见两者是高度重合的,唯一的区别只在“17-12 系统需求规范”与“17-11 软件需求规范”这一项上。因此,在实际项目人员紧缺的情况下,这两个过程域的工作产品输出可以在一定程度上重合,但需要分清界限:
涉及“17-12 系统需求规范”的内容归属系统
涉及“17-11 软件需求规范”的内容归属软件
这对于后续界定验证职责、问题根因分析至关重要。
至于这两类的需求,前面举了AEB的例子管中窥豹,如下给出ASPICE中【工作产品特性】附录表中对两者的描述给出参考。
17-12 系统需求规范 | 17-11 软件需求规范 |
系统需求包括:系统的功能和能力; 业务、组织和用户需求; 安全(safety)、安全(security)、人因工程(人体工程学)、接口、操作和维护的需求; 设计约束和合格需求。 | · 识别使用的标准 |
这样的分类在实际的落地中根据实际情况会有不同考量,如需求的粒度、非功能需求的完备性、具体的分工等等,需要实践的积累才能日渐成熟。如果实在弄不清的话,只要记住——涉及软件实现细节的归属软件需求,否则归属系统需求,系统需要适度控制对软件细节的控制欲,扮演好产品经理的角色以满足客户需求为第一要务。
03.
时机
三千多年前,智慧的所罗门王在他的《传道书》中记下了“天下万务都有定时”的观察,在人看来或好或坏的事情,都有一定的时机——时机未到,费尽心血最终不过徒劳无功;时机一到,顺势而为瞬间便能水到渠成。映射到流程体系在现实项目中的落地,也有相似的情形,若是把握时机在对的时间做对的事情,那么将势如破竹。讨论在不同情形下把握时机的策略,可以分成价值观-方法论-执行力三个层面,
价值观
流程体系推广之时,例行公事的少不了各级领导的表态——“我们一定要彻底贯彻实施XXX,各个部门都要认真执行不打折扣……”。此处的XXX可以替换成各类流程体系的名称——ISO、IATF、CMMI、ASPICE,等等等等。当然,如果领导连这样的表态都没有那这件事情基本就凉了,不过,真的轻易就信了那就“图样图森破”了,这到底是不是单纯的场面话,还得看看落地的实际情况。
丰田生产方式TPS中强调“三现主义”——指的是现场、现物、现实,就是说,当发生问题的时候,管理者要快速到“现场 ”去,亲眼确认“现物”,认真探究“现实”,并据此提出和落实符合实际的解决办法。这个在制造业中广泛应用的原则,同样可以应用到软件开发领域,看看一线开发人员在实际工作的时候是不是有这样的声音——
“连代码的bug都改不好天天加班到两点了,架构设计文档真的没空做。”
“这次交付太急,审核可不可以先不做了,下次一定配合。”
“要遵守流程可以,跟我老板说,给人我就干。”
……
如果这些表述都是真实的,一线人员长期主要面临的挑战来自资源不足、工期太紧、任务太多,那么属于共同原因(common cause)而非特殊原因(special cause),上梁不正下梁歪,本质上可能是管理层“不派人、不派钱、只派活”的态度问题。领导们场面话说的漂亮就是不给人不给时间,那很可能是“价值观”层面出了问题。在这里,为了限定“价值观”的讨论范围,可以先看看ISO9001的7大质量管理原则,列表如下——
在这里,我们讨论的流程体系的各种具体落地,本质上是属于“过程方法(Process Approach)”,也就是7大质量管理原则的第4个,思考为什么组织定义的过程方法为什么没能贯彻下去的时候,不可忽略的前设问题应当是“前三个原则”落实的怎样了?——
1.客户为中心(Customer Focus)
2.领导力(Leadership)
3.全员参与(Engagement of People)
在7大原则中,这前3项原则处在价值观层的层面,而后4项原则属于方法论的范畴,而前3项的价值观,则是决定包含“过程方法(Process Approach)”在内的后4项原则的方法论能够落实的前提。
如果“客户为中心(Customer Focus)”只是销售对甲方的天花乱坠,其中关于代码质量、流程监管等等的条款项目工程团队选择性忽略只顾着拿到需求往下做,那就是简单的确保测试覆盖率100%都得打折扣;
如果“领导力(Leadership)”中的总监们对流程体系缺乏基本常识,那么让他们投入资源在项目中落地规范的难度可想而知 ;
如果“全员参与(Engagement of People)”达成的共识是连架构设计文档都是做给流程部门看的,那么应付式文档只能是常态。
所以,当一个过程方法推行的时候,如果遇到的主要阻力是关于“要不要做”的各种推诿拒绝,那么很明显是价值观层面出了问题;而如果遇到的主要阻力是“该怎么做”的各种具体难度,那么就应当在方法论上进行提升,将理论落地实践做好。
说了这么多,在这种情况该怎么办呢?事实上,无论是程序员、SQA、项目经理,甚至部门总监,作为个体在应对“价值观”层面的问题都会有深深的无力感——“大家都这样、行业都这样、我能怎么样?”。
达则兼济天下,穷则独善其身——
作为程序员,需求-架构-详设-代码-测试-改bug循序渐进,哪一环来不及做至少自己心里有数,合理安排自己的工作任务不要勉强,遇到问题注意方法,样例可参考 调试一段代码两个小时都没搞定,继续死磕还是寻找其他方式,你一般会怎么做?
作为SQA,牢记“客观评估”的原则(参考CMMI),对于不符合项该记录的记录、该跟踪的跟踪、该升级的升级,切忌为了事情无法推进控制不了主观情绪跟同事“互怼” 。(当然说起来容易做起来难,很考验情商)
作为项目经理,协调各方人员一起推动项目本来就是极度困难的任务,靠“野路子”的手段虽然短期有效,但为了长期发展还是需要根据组织规则按部就班。
作为部门总监,看似风光,实则面临各种压力和约束,若是使用得当,流程体系不是阻力而是助力,可以分担大部分的压力。
在现代社会,对于公司而言,没有人是不可取代的,否则裁员就不存在了;对个人而言,没有公司是不可取代的,否则跳槽就不存在了。因此,在这样双向选择开放的社会氛围下,个人劳动者无论处在什么位置上,对公把“打工人”的心态放好按部就班把工作完成,对私平衡生活持续学习提升竞争力,那边够了。
以上讨论了流程体系的落地在“价值观”层面的挑战和应对策略,对于方法论和执行力层面的考虑,将根据下面的列表继续展开。
层面 | 挑战 | 心态 | 策略 |
价值观 | 态度不正 | “打工人” | 按部就班 |
方法论 | 资源不足 | “聪明人” | 术业专攻 |
执行力 | 能力不够 | “牧羊人” | 求知若渴 |
阅读原文,关注作者知乎!