K4-04 软件版本、配置与变量管理
课程代码 K4-04 · 板块 K 控制、软件与标定 / K4 嵌入式软件与开发 时长 约 4.0 小时(6 讲 + 1 次版本与变更流程实操) 适合对象 控制工程师、软件配置管理工程师、项目管理岗(必修) 前置 K4-02 基于模型开发(MBD):Simulink 建模与代码生成 基于模型开发(MBD):Simulink 建模与代码生成——模型与生成代码这两类产物正是本课的管理对象;体系外前置(需自备):版本控制工具(如 Git)的基础常识 本讲义定位 讲师授课蓝本 / 学员自学讲义,是 K4-04 大纲的完整展开版
引言:每个文件都有版本号,不等于这一版能被重建出来
配置管理这件事,在多数团队里是以「我们用了版本控制工具」的形态存在的:代码在库里,模型在库里,每次提交都有记录,每个文件都查得到自己的历史。这一层没有难度,工具手册讲得比任何一门课都细。真正卡住人的是三个场合,而它们没有一个是「版本控制工具不会用」。
第一个场合在售后:一台车返回来,问它装的到底是哪一版软件。台账里能查到一个号,车上读回来是另一个号;或者两个号对上了,却没有人说得清那一版里包含了哪些变更、又没包含哪些。这件事发生的时候,前面所有的提交记录都还好好地躺在库里——它们证明的是「谁在哪天改了哪个文件」,唯独不证明「交出去的那一份是由哪些输入唯一确定的」。第二个场合是同一个缺陷第二次出现,它有两种长相:一种是这个缺陷在另一个车型上从来没被修过——两个变型各自维护一份代码,共性缺陷只在一份里改了,另一份带着老缺陷继续出货,而漏改的那一份测试还全过(它按自己那份的用例测,测试当然是绿的);另一种是它在同一个车型上又回来了——紧急修复直接在发布分支上改完就发,没有合回主干,下一个常规版本又把它带了回来,而第二次出现时它看起来像一个新缺陷。第三个场合在评审桌或评估现场:事都做了,证据不成链。文档在,评审记录没有;追溯表有,只有正向那一半;变更记录里写着二十条,仓库里对得上的提交只有十二条。还有一种更隐蔽的:谁也没改过一行业务代码,只是把代码生成器换了一版,同一份模型吐出来的 C 代码就不同了——而这件事根本没有触发任何一次变更请求,因为工具链压根不在被管的范围里,它连一个入口都没有。
所以本课教的不是「怎么用版本控制工具」,而是怎么把一组产物拴在一起,让它们能被一起冻结、一起改、一起发出去,以及怎么验它做没做到。学完你应该能做六件事,每一件都对应一个当场可验的动作。设计一套版本号方案,并说清接口变更、功能新增、缺陷修复这三类变化各自落在哪一位——交付物是一份编号约定,自检只有一句「拿到这个号的人,知道自己要不要跟着改吗」。搭出变型管理方案,用参数化与特性开关而不是复制代码库来支撑多车型复用——交付物是一张变型矩阵,它的每一行唯一对应一组可写配置字取值与一个发布件。建立需求、模型、代码、标定数据之间的基线关系——交付物是一份配置项归属表与基线定义,判据不是「列得全不全」,是「拿掉其中任一项,还能不能唯一重建出同一份交付件」。设计一套变更管理流程(提出、评审、实施、验证、关闭)——交付物是变更请求的记录要素与每一步的出口证据,⚠ 每一步的出口都必须是「拿得出某样东西」,不是「某个人同意了」。说清软件配置管理与标定数据版本管理各自管什么、边界画在哪——交付物是两张互不重叠也不留空档的归属表。把本课的每一件产出物各自对上软件过程参考模型的一个过程域,并说清过程评估看的是过程有没有被执行、被管理,证据能不能重复取到,而不是技术水平高低。
全课六讲。第 1 讲把位置摆平——一套 ECU 软件同时供多车型与多硬件版本复用时会撞上什么、哪些东西必须被管起来而哪些不该进来、与机械件图纸版本管理的类比在哪一半成立哪一半不成立、以及「能追溯」这句话的操作化定义与追溯链上那八个高发断点。第 2 讲讲编号与骨架——语义化版本三位各自的射程、在汽车控制软件里「接口」到底包括哪些东西、主干开发与特性分支各自的适用条件与代价、基线为什么是一次横切而不是代码的一个标签、以及模型文件的合并冲突为什么是结构问题不是态度问题。第 3 讲讲变型——变型的两个来源、承载变型的三种手段怎么比、组合空间的上界与「实际要维护、要验证的量」是两回事、以及变型矩阵与可写配置字与发布件这三者为什么必须一一对应。第 4 讲讲变更——变更请求五步各自的出口判据与产出证据、变更来源一共有哪几类(其中最容易整类漏掉的那一类连触发入口都没有)、影响分析必问的五个维度与各自的去向、紧急修复与常规迭代的流程差异、以及追溯矩阵的双向读法。第 5 讲讲发出去的那一包——发布件由什么构成、按「会烧进 ECU 的东西」清点会漏掉哪三类、跨企业交付要追加什么、刷写完整性的三道校验各防什么且为什么互不推导、以及为什么必须随件带一份对上一版本车端数据布局的兼容声明。第 6 讲收口到边界与闭环——三方配置管理的分工怎么划、三套工具之间靠什么号互相引用、版本标识为什么必须能从车上读回来才算闭环、以及本课的产出物各自落在哪个过程域上。前置是 K4-02 基于模型开发(MBD):Simulink 建模与代码生成(模型与生成代码这两类产物是本课的管理对象);版本控制工具的基础操作属体系外前置、需自备。
钉子①:配置管理管的不是「某个文件的版本号」,而是「一组产物在某一时刻的相互一致性」——有意义的最小单位是那一整组被同时冻结的东西,不是单个文件的版本。一份代码单独有版本号,说明不了任何事。有意义的是这样一组东西被同时钉住:需求(在控制域里它的载体是控制功能规格文档)、模型、生成代码与手写代码、标定数据集、测试规程与结果证据、诊断描述文件与故障码清单、通信矩阵、工具链及其配置。纳不纳管的判据只有一句:把这一项拿走,剩下的还能不能唯一地重建出同一份交付件?不能,它就必须在这组里;能,它就不该进来——进来只会让每一次改动都多走一遍变更流程,最后逼着人绕过流程,而人一旦开始绕,被管的那个库就不再等于真实状态了。⇒ 全课用这一条解释后面每一件事:工具链为什么必须被管起来(换一版代码生成器,同一份模型吐出的代码就不同 ⇒ 代码不再被这一组唯一确定);标定数据与代码为什么各有各的版本号、却必须在发布件这一层重新对齐(两个变化速率差得很远的产物绑死会互相拖累,不绑又失去一致性 ⇒ 只能到更上一层去重建一致性);诊断描述文件为什么必须与软件同批发布(车上置出的码与诊断仪库之间的对应关系,本身就是这一组的一部分);车上为什么必须能把版本读回来(那是这一组在车端的投影,读不回来就只能靠台账相信,验证不了);变型矩阵、可写配置字与发布件三者为什么必须一一对应(变型是这一组的一个维度,对不上就是把甲车型的那一组装进了乙车)。⚠ 这条判据同时给出反方向的裁剪,第 1 讲会展开:漏纳管与过度纳管各有各的代价形态,⛔ 而「重要」从来不是纳管判据。这条判据的图示不在引言重复,统一放在第 1 讲 1.2(图1)正式解读。
钉子②(它是钉子①的可执行版):这套东西做没做到位,判据不是「有没有流程文件」,而是——任取一个已经交出去的软件件,能不能在有限步内、不靠任何人的记忆,重建出它的全部输入,并逐条解释它与上一版的每一处差异。这是一句可以当场演练的话:随手指一个已发布版本,要求在不问任何人的前提下拿出四样东西——① 这一版被冻结时那一组产物的全部条目及各自版本;② 从上一版到它之间关闭的全部变更请求,以及每条的影响分析结论;③ 每条变更请求对应的实际提交与验证证据;④ 这一版对上一版车端数据布局的兼容声明。哪一步走不通,哪里就是这套配置管理真正的缺口——而它与「文件写得全不全」几乎没有关系。⇒ 第 6 讲会把这条判据与过程评估里那六个典型掉分点逐条对上:文档在但没有评审记录、追溯只做单向、变更记录与实际提交对不上、紧急修复未合回主干、工具链版本没被管起来、测试用例没随需求变更更新——会看到它们恰好各自让这个重建动作在某一步断掉,所以它们不是六条互不相干的毛病,是同一个判据的六个失效点。这也正是「事都做了、证据不成链」这句话的确切含义:掉的是过程属性,不是技术水平。
★ 本课最容易被读反的是这样一句:「主版本=不兼容接口变更、次版本=新增功能、补丁版本=缺陷修复」这个定义是对的;但把它反过来当成「补丁版本=下游不必重新验证」,方向恰好反了。拆开看三步。版本号声明的是接口契约的语法兼容性:调用方不改一行代码还能不能编过、通信矩阵里的信号还在不在、标定量的地址与类型有没有变、诊断服务与数据标识符的定义动没动——它回答的是「你要不要跟着改」。而下游(标定、验证、整车、售后)真正关心的是行为的语义变化:这一版在同样的输入下,会不会做出不同的动作。一次纯粹的缺陷修复按定义落在补丁位,却完全可以改变热管理的控制行为——修好一处多通阀切换判据,整车的模式切换时刻就变了,前期标定的结果可能整片要复核;反过来,一次新增功能落在次版本位,如果这个功能在本车型根本不使能,在本车型上可能什么都不必重验。两件事之间没有函数关系:版本号的哪一位变了,与需要多大的回归范围,不是同一条判据链,⛔ 本课的图上也不会用同一条引线把这两件事连起来。读者会做错的那个具体动作:拿到一版「只升了补丁位」的软件,据此在发布评审里勾掉回归验证,或者把回归范围缩到只跑冒烟用例。⚠ 这里最难发现的形态不是「版本号乱升」,而是版本号升得完全合规、下游照样判错——他们把一个语法层的标记,当成了语义层的授权。⇒ 正确口径:版本号是索引,变更请求的影响分析才是授权。至于回归范围怎么裁、凭什么判据裁,由 K4-08 控制软件回归验证:基线与激励库、回归范围裁剪、自动执行与失败分诊 承接,⛔ 本课不自造裁剪判据,只负责保证「影响分析这一栏必须被填、填的内容能被追溯到、且它的结论必须落到发布评审的放行条件里」。这一条在第 2 讲被正面点破并配图,第 4 讲讲影响分析时再回到它。
⚠ 第二条容易读反的,本课在第 3 讲点破:「特性开关一多,组合数按 2 的 n 次方指数增长」这句是对的;但把它读成「所以要少加特性开关」,会把人推回复制代码库那条路。2 的 n 次方描述的是组合空间的上界,不是要维护、要验证的量。真正要维护的是项目显式声明过的合法组合集——有限、可枚举、由车型项目决定;要验证的量则取决于开关之间是否正交:一组互不耦合的开关,验证可以按维度分解,量级近似各维之和,只有真正互相耦合的开关才必须按组合去测。而少加开关不会让车型变少,只会让差异回到代码分叉里去——那才是真正不可合并的增长,因为分叉的维护成本无法按维度分解:一次共性缺陷修复要在每个分叉里各做一遍,而且漏做一个不会报错。读者会做错的那个具体动作:为了「控制变型爆炸」,拒绝把新出现的差异参数化,改用复制代码库、或者再分一支条件编译。⇒ 正确口径:要控的不是开关数,是开关之间的耦合;外加一条硬要求——合法组合集必须显式成表的一行,⛔ 不许把「没写进表的组合」默认成禁止或不存在,因为默认值不会被测试覆盖,一旦被触发就是未定义行为。
⚠ 第三条读反的范围小一些,但同样是做反的:「配置管理是为了可追溯,所以东西越多进配置库越好」。纳管的判据不是「重不重要」,是钉子①那一句。按「重要」纳管会同时犯两个方向的错:一方面把大量并不参与决定交付件的中间产物拖进变更流程(每改一次都要走一遍评审,于是人开始绕过流程,被管的库随即失真),另一方面又漏掉那些「看起来不是我们的东西、却决定输出」的项——工具链版本、代码生成配置、编译与链接选项、第三方库与基础软件版本。⚠ 后者的漏法是整类不出现:它们从来就不在「我们组写了哪些文件」这条枚举线索上,而表面上那张表还是齐的。
这就引到本课反复要用的一个动作。凡是要「列一张表」的地方——哪些东西必须被管起来、什么会触发一次变更、「版本」这个词到底指哪几个对象、一份发布件由什么构成、追溯链上有哪些断点——本课一律先把全集画出来、再逐项核射程,而不是顺着自己最熟的那条线索往下数。这不是讲究:沿单一线索枚举时漏掉的从来不是「少了一条」,而是整类不出现,而且那张表看起来还是完整的。四个已经踩实的例子。其一,沿「软件开发过程中我们自己写出来的文件」数配置项——这条线索问的是「我们组产出了什么」,它只数得出署我们名字的东西,于是整整六类不出现(六类的完整划分与各自的去向见 1.4):不是我们写却决定输出的那一整类(工具链、编译与链接选项、第三方库与基础软件)、只描述而不实现的那一类(诊断描述文件、通信矩阵、刷写序列)、只在过程里存在却被过程评估当作工作产物的证据类(评审记录、追溯矩阵本身、覆盖率报告)、决定「在哪台机器上用什么姿势产出」的构建与环境那一类(构建脚本、流水线定义、构建机镜像)、发布之后由产线与售后消费的那一类(变型矩阵表、可写配置字定义、售后码表),以及别人交给我们的那一类。其二,沿「需求变了」数变更来源——这条线索默认变更都是从上游需求下来的,于是所有不经过需求文档的变更整类不出现;其中最贵的是外部依赖驱动那一类,它一行业务代码都不改,却会改变生成出来的代码。其三,沿「会烧进 ECU 的东西」数发布件——那条线索只数得出最终进 Flash 的字节,而发布件里最容易漏的那几类恰好一个字节都不进 Flash:面向下游流程的件、证据包,以及声明类。其四,「版本」这个词在本课至少指七个互不相同的对象,它们的口语名字全都叫「版本」,而变化频率、命名规则、责任方、能不能从车上读回来各不相同、且互不推导——这是本课最容易在会议上吵半天的一处,第 6 讲会把七个口径分列开。
射程也先划清,免得在正文里白找。本课的落点是出厂前这套资产怎么被拴在一起、怎么被改、怎么被发出去:配置项的纳管判据与基线、版本号与分支策略、变型编码与变型矩阵、变更请求与影响分析、发布件构成与刷写完整性、以及三方配置管理的边界,都在射程内。射程外的,本课只给类型与去向,不给限值、不给条款内容、不给判据:车端自产数据的结构、版本号规则与迁移函数由 K4-06 控制器非易失存储设计:学习值、诊断数据与累计量的持久化 承接(本课只交那份兼容性声明本身与它的三档口径);回归范围怎么裁、凭什么判据裁由 K4-08 控制软件回归验证:基线与激励库、回归范围裁剪、自动执行与失败分诊 承接;控制功能规格的字段口径、评审组织与基线冻结时点由 K4-07 热管理控制功能规格(软件需求)的编写、评审与向 Tier1 交接 承接(本课只把「需求」当成一个必须被管起来的对象);跨企业交付的形态谱、权限分级与联合验证签署由 K4-09 热管理控制软件的跨企业交付边界:交付物形态、DIA/SEooC、权限分级与联合验证签署 承接(本课只在发布件构成里列出跨企业追加的那四项并标去向);标定文件的库侧建库、分支合并与追溯由 K6-05 标定数据管理与版本控制 承接(本课只讲两者为什么不共用一个版本号、在发布件层怎么重新对齐);产线工位、按车辆识别码写入与错写拦截由 K6-09 产线下线与售后标定:工位项清单、配置写入与学习值管理 承接;诊断服务、故障码机制与数据标识符的定义由 K5-01 OBD/UDS 诊断与故障码(DTC)设计 承接(本课只用「把版本标识读出来」这一个动作);验证层级与覆盖率的定义由 K4-03 MIL/SIL/HIL 验证流程 承接(本课只把测试件当作必须纳管的配置项);模型与代码生成链路由 K4-02 基于模型开发(MBD):Simulink 建模与代码生成 承接(本课只讲模型文件的合并冲突,以及代码生成配置为什么必须被管起来);分层架构与构件配置由 K4-01 热管理嵌入式软件架构与 AUTOSAR 基础 承接;签名与密钥体系、安全启动由 K2-04 网络安全与 OTA 安全基础 承接,刷写事务与回滚由 K7-02 软件定义热管理与 OTA 迭代 承接;需求管理工具与通用的双向追溯做法由 M1-04 需求管理与追溯(DOORS 等) 承接,里程碑与基线冻结点的对齐由 M1-01 汽车研发流程(APQP/IATF16949)与热管理里程碑 承接;仿真侧的资产(仿真模型、网格、求解设置、物性表、后处理脚本)整块由 J7-07 仿真任务的输入、交付与模型资产管理 承接,本课一字不讲。
标准这一层,本课引用三个体系,它们各管一层:功能安全体系里的支持流程标准(ISO 26262-8),含配置管理与变更管理条款;软件过程参考与评估模型(Automotive SPICE),本课的每一件产出物各自对应它的一个过程域;质量管理体系标准(IATF 16949),含变更管理要求。此外第 6 讲会用到统一诊断服务标准(ISO 14229-1)里标识类数据标识符的那一段。⛔ 而这四者的条文内容,本课一份都没有取到原文——所以正文与图上只写标准号、管什么、去哪查,不写条款号、不写限值、不写与完整性等级相关的任何要求;⚠ 版次与年份一律以现行目录为准、引用前须核,⛔ 不写成一个具体值。⚠ 过程参考与评估模型还要额外多一句:它有两版并行流通,后一版调整过过程域名称与工作产物编号,引用时必须显式声明所依的是哪一版,⛔ 不得混引。★ 本课最容易犯的一处自封是「我们的配置管理已经符合某某标准」——上面这几条口径里,没有任何一条给出了可判真假的符合性判据,⛔ 所以这句话本课说不出口,正文里也不会出现。
最后交代一类数,同样免得在正文里白找。这些量本课一个都不给:项目实际的特性开关数、已发布变型数与需要验证的组合数;追溯覆盖率的目标值;分支数、发布分支的冻结期长度、变更请求的关闭时限、紧急修复的响应时限、基线打点频次;工具链各件(代码生成器、编译器、静态分析工具、第三方库、基础软件)的具体版本号;校验和与签名的算法选型、位宽与密钥长度;覆盖率指标的目标值与验证层级的选择判据;控制器存储与算力的占用比例与裕量口径;以及案例里的车型数、缺陷数与流入市场的规模。它们全是平台相关量,取决于车型规划、硬件配置谱、团队规模、项目节奏与本项目所依的过程模型目标,只能由本项目定——⛔ 本课不给,⛔ 也禁止抄上一代平台的数,⛔ 图上同样不会偷偷画一条门槛线或一个刻度代替它(凡属这一类的量,图上都画成可沿轴自由平移的带,并标明它由本项目给出)。⚠ 其中两处还要各多一句:工具链版本必须记到能复现的粒度,即含配置集与编译链接选项,⛔ 不只是一个主版本号;而「一般为多久」「一般要达到多少」这类看起来像区间的说法,本课同样不写——那仍然是给数。
本课能给的数只有三类。一类是编号约定与代数结论。语义化版本三位的定义与升位规则(升高位时低位归零)可以给准确表述,⚠ 但要同时说清两件事:汽车行业普遍采用的是它的变体(常见做法是在三位之外再挂分支标识或构建号),本项目取哪一套须自行声明;⛔ 而它不是任何汽车标准的强制要求——写成强制要求,就是给了它一个它没有的权威。组合空间的上界关系(最坏情况下 N = 2ⁿ,n 为二元特性开关数)是组合数学的直接结论,不是实测值,⚠ 它的两个前提要写清:所有开关都是二元的、且完全互相耦合;⛔ 不得据它外推任何项目的实际变型数或需验证组合数。追溯覆盖率的定义式(已建立追溯关系的需求数 ÷ 总需求数)是定义不是实测值,⚠ 但分母口径必须先写死——分母算不算已注销需求、已推迟需求、非功能需求与继承自平台的需求;口径不写明,这个比值可以被调成任何想要的数,也就不许拿它与任何别的数比较。第二类是本课自己归纳的结构划分,用到时都会标明是本课归纳的、⛔ 不是哪份标准既有的:发布件的五件最小集与三类不进 Flash 的追加件、影响分析的五个维度、追溯链的八个断点、以及车端数据布局兼容性的三档(可直接沿用 / 需迁移 / 需清除重学,这一划分与 K4-06 控制器非易失存储设计:学习值、诊断数据与累计量的持久化 的边界约定一致)。第三类是标准与服务的标识本身:标准号、以及读版本标识用到的那一个诊断服务标识,⚠ 一律只写它在本课的用途与去向,并附「须按现行版本核原文」。⛔ 除此之外,正文里凡是要走一遍口径的例子,一律使用明确标注为教学假设值的数,它们不对应任何平台,⛔ 禁止照抄取用。这门课的交付物不是一套推荐做法,是一串「随手指一版,都能不靠任何人的记忆把它重建出来」的证据。
第 1 讲 软件也要配置管理:管的不是文件的版本号,是一组产物在某一刻的相互一致性
「配置管理」这四个字最容易被当成一件早就解决了的事:代码进了版本控制工具,每次改动有提交记录,发布时打一个标签,还要怎样?这门课要说的是,上面这句话没有一个字是错的,而它离本课要的东西还差一整层——版本控制工具管的是文件的历史,配置管理管的是一组产物在某一刻能不能被同时钉住、并在事后被唯一地重建出来。两者之间隔着的,恰好是热管理软件出问题时最贵的那几种形态:一次共性缺陷只在一个分叉里修好、另外几个带着老缺陷继续出货;半年后要复现某个已经发出去的软件件,模型还在、代码也还在,却谁也说不清当时用的是哪一版代码生成器;车上置出一个故障码,售后的诊断仪把它解读成另一个故障。⇒ 本讲不讲任何一步工具操作,只做六件事:把问题背景说成一个可判真假的命题(1.1);给出本课的机制层判据——基线元组与可重建性(1.2);把「做没做到位」换成一个当场能演练的动作(1.3);按全集画法列出配置项,并点破沿单一线索枚举时会整类漏掉的六类(1.4);给「能追溯」一个操作化定义与它的八个断点(1.5);最后拆开那个人人都在用的图纸类比,说清它成立到哪里为止(1.6)。⚠ 本讲一个平台相关的数都不给:配置项条数、配置库规模、基线打点频次、追溯覆盖率的目标值、案例里的车型数与分叉数,全部属于须由本项目确定的量。
1.1 「改一个坏三个」会被测试抓住;真正贵的是「改一个漏三个」,它不会被任何测试抓住
是什么。本课的问题背景可以写成一个可判真假的命题:一套热管理 ECU 软件要同时供多个车型与多个控制器硬件版本复用;承载这些差异的方式如果是代码分叉,改动就会在两个方向上失控。第一个方向是改动扩散到了不该扩散的地方——俗称「改一个坏三个」:为甲车型调了一处逻辑,共用的那一段被一起改了,乙丙丁三个车型跟着变了行为。第二个方向是改动没有扩散到该扩散的地方——「改一个漏三个」:一处共性缺陷只在其中一个分叉里被修好,另外几个分叉带着同一个老缺陷继续出货。
为什么。两个方向的危险程度差着量级,而人的直觉恰好把它们排反了。「改一个坏三个」听起来更吓人,但它会在测试里暴露:被改坏的那几个分叉一旦跑回归,行为变了就会有用例挂掉,问题在出厂前被拦住,代价是一轮返工。「改一个漏三个」则不会在任何一次测试里暴露——漏改的那个分叉测试全过,因为它本来就是老样子,它的测试用例也是按老样子写的,没有任何一条用例会去问「你为什么没有跟着那次修复一起变」。⇒ 于是缺陷跟着车流入市场,直到售后返回件做根因分析时才第一次被看见,而这时它已经装在了成批的车上。本课后面要建立的整套机制——基线、变更请求、追溯矩阵、变型编码——其中相当一部分的存在理由,就是把第二个方向从「靠人记得」变成「机制上不可能漏」。
工程量级/典型值。⛔ 本条不给任何数:一个平台同时在管的车型数、代码分叉数、缺陷流入市场的规模、返修或召回的量级——它们既属平台相关量(取决于车型规划与团队组织,须由本项目确定),也属脱敏红线。本课引用的那个案例只写决策链的结构:有热泵与无热泵两种配置分别维护两份代码 → 一次共性缺陷只改了一份 → 漏改的那一份测试全过 → 带着缺陷流入市场 → 售后返回件才发现。⛔ 案例统一写「某纯电平台」,不出现任何企业名与车型型号,也不编造规模数字。本条真正给出的量只有一个,而且是定性的:两个方向的暴露时点不同——一个在出厂前,一个在售后端。
易错点。最常见的一处,是把这件事理解成「人不够仔细」,于是把对策定成「加强评审」「修复时多问一句还有哪几个分支要改」。⚠ 这条对策无效,而且它的无效有明确的结构原因:只要差异是靠复制代码库承载的,「漏改」这个事件就没有任何机制能发现它——没有编译错误、没有用例失败、没有一张表会报警,评审再多也只是把漏改的概率从高降到略低,而不是降到零。⇒ 正确的理解是:这是承载方式的问题,不是态度问题。三种承载方式各自会把「漏改」变成什么形态,第 3 讲用一张对照表把它讲死;本讲只需要读者接受一件事——凡是「只能靠人记得」的环节,最终都会漏,而且漏了不报错。
1.2 有意义的最小单位是基线元组,不是任何单个文件的版本号——纳不纳管只有一条可重建性判据
是什么。这是本课的第一根钉子,全课每一件事都要用它解释。⇒ 配置管理管的不是「某个文件的版本号」,而是「一组产物在某一刻的相互一致性」;有意义的最小单位是基线元组,不是单个文件的版本。一份代码单独有一个版本号,说明不了任何事:它没有告诉你这份代码是从哪一版模型生成的、用的是哪一版代码生成器、配的是哪一份标定数据集、它的测试证据在哪、它置出的故障码由哪一份诊断描述文件解读。有意义的是这样一个元组被同时冻结:需求(在控制域里,这个配置对象的实际载体是控制功能规格文档)、模型、生成代码与手写代码、标定数据集、测试规程与结果证据、诊断描述文件与 DTC 清单、通信矩阵、工具链及其配置。
而「什么该进这个元组、什么不该进」,本课只给一条判据,它可以在任何一次争论里当场使用:
把这一项拿走,剩下的还能不能唯一地重建出同一份交付件? 不能 ⇒ 它必须在元组里;能 ⇒ 它不该进来。
★ 这条判据是本课归纳的,不是任何标准的既有条款,也不是哪本手册里的原话——引用它的时候请照这个身份引用。⚠ 与本课相关的外部体系有两个,本课只写标准号与去向、不写条款内容与限值:功能安全体系的支持流程标准 ISO 26262-8 含配置管理与变更管理条款;质量管理体系标准 IATF 16949 含变更管理要求。⛔ 两者的具体条款、限值与等级相关要求,本课一律不转述;版次与年份以现行目录为准,引用前须核原文,⛔ 不得把版次单值化写死在讲义或项目文件里。
为什么。这条判据之所以值得当钉子,是因为本课后面每一讲的必要性都能由它直接推出来,而不必再各讲一套理由:
- 为什么工具链版本必须纳管:同一份模型,换一版代码生成器吐出的 C 代码就不同 ⇒ 元组没锁死,代码就不是被基线唯一确定的,重建箭头断掉。
- 为什么标定数据可以另有一套版本号、却必须在发布件那一层重新对齐:标定数据集与代码的变化速率差得很远,绑死会互相拖累(改一个标定量要走完整的代码发布流程),不绑又失去一致性 ⇒ 只能到更上一层(发布件)去重建这份一致性。
- 为什么诊断描述文件必须与软件同批发布:车上置出的码与诊断仪库的对应关系本身就是元组的一部分,它不在元组里,售后端就解读不了这台车。
- 为什么车上必须能把软件版本与标定版本读回来:那是元组在车端的投影;读不回来,就只能靠台账相信,而台账是不能被验证的。
- 为什么变型矩阵、可写配置字与发布件三者必须一一对应:变型是元组的一个维度,对不上就是把甲车型的元组装进了乙车。
同样重要的是这条判据的反方向:拿掉之后照样能重建的东西,不该进配置库。它进来不会带来任何一致性收益,只会让每一次改动都多走一遍变更流程;而流程一旦变得比它保护的价值更贵,人就会开始绕过它——绕过之后配置库随即失真,此时它比一开始什么都不管更危险,因为大家还以为它是准的。
工程量级/典型值。⛔ 本条不给配置项条数、配置库规模、基线打点频次中的任何一个数——它们全属平台相关量,取决于产品范围、工具链集成程度与项目节奏,须由本项目确定,⛔ 也禁止照抄上一代平台的设置。本条能给的是判据本身,以及它两个方向失守时各自的代价形态:漏纳管的代价是「重建不出来」,它在半年后换人时才暴露;过度纳管的代价是「流程被绕过」,它从第一天起就在悄悄发生,而且不会有人报告。
易错点。两个,而且都很常见。① 把「重要」当成纳管判据——「这个文件很重要,也放进配置库吧」。⚠ 这句话同时会犯两个方向的错:一方面把大量不参与决定交付件的中间产物拖进变更流程;另一方面照样漏掉那些「看起来不是我们的东西、却决定输出」的项(工具链版本、代码生成配置、编译与链接选项、第三方库与基础软件版本),因为按「重要」这条线索去想,它们根本不会被想起来。② 把基线理解成「某一刻的代码快照」——一个代码仓库的标签不是基线,它只钉住了一条泳道。基线是横着切过需求、模型、代码、标定、测试证据、工具链这几条各自演化的泳道的一条线,只切代码那一条不叫基线。这一点第 2 讲 2.3 用泳道图展开。
1.3 判它做没做到位,只有一个动作:随手指一个已发出去的软件件,不问任何人,把它重建出来
是什么。这是本课的第二根钉子,它是第一根钉子的工程层可执行版。⇒ 这套配置管理做没做到位,判据不是「有没有流程文件」,而是——任取一个已经交出去的软件件,能不能在有限步内、不靠任何人的记忆,重建出它的全部输入,并逐条解释它与上一版之间的每一处差异。这是一句可以在会议室里当场演练的判据:随手指一个已发布的软件件,要求在不问任何人的前提下拿出四样东西——
- 它的基线元组的全部条目及各自的版本标识:需求(控制功能规格文档)、模型、生成代码与手写代码、标定数据集、测试规程与结果证据、诊断描述文件与 DTC 清单、通信矩阵、工具链及其配置,每一项都要指得出是哪一份、哪一版。
- 从上一版到它之间关闭的全部变更请求,以及每一条的影响分析结论:不是变更请求的标题列表,是每条的影响分析写了什么、判了哪些下游受影响。
- 每一条变更请求对应的实际提交与验证证据:从变更请求能走到具体的提交,从提交能走回变更请求,两个方向都要通;并且每条变更请求要挂得上它的验证证据。
- 这一版对上一版车端数据布局的兼容声明:可直接沿用 / 需迁移 / 需清除重学,三档取哪一档。⚠ 这三档的名称与含义是本课与 K4-06 控制器非易失存储设计:学习值、诊断数据与累计量的持久化 之间约定的口径划分,★ 它是本课归纳的,不是某个标准既有的分类;三档各自的判定依据、车端数据结构与迁移函数本体由 K4-06 控制器非易失存储设计:学习值、诊断数据与累计量的持久化 承接,本课只交那份声明。
为什么。这个动作把两句抽象的话变成了一次可复现的实操。第一句是「过程有没有被执行、被管理,证据能不能重复取到」——过程评估看的正是这个,而不是技术水平高低;第二句是「事都做了、证据不成链」——大量团队的真实状态。⇒ 这个动作同时解释了为什么「文档写得全」与「配置管理做得好」几乎不相关:文档是这四步里最容易做到的那一部分,一份写得漂亮的配置管理计划完全可以与一次走不通的重建同时存在。而反过来,只要这四步全都走得通,即使文档写得朴素,这套机制也是成立的。
更实用的是它的定位法:哪一步走不通,哪里就是这套配置管理真正的缺口。第 1 步走不通,缺口在配置项清单与基线(漏纳管,或基线只钉了一条泳道);第 2 步走不通,缺口在变更请求流程(有提交没有变更请求,或影响分析这一栏是空的、填的是「影响小」这种无判据结论);第 3 步走不通,缺口在追溯(变更记录与实际提交对不上,或证据不带基线号);第 4 步走不通,缺口在发布件的构成(声明类整类没有进发布件——它们一个字节都不进 Flash,所以「按烧录内容清点」的验收永远看不见它们)。这四处对应的正是本课第 4、第 5 讲要处理的东西;第 6 讲把过程评估的六条典型掉分点逐条挂回来,说清每一条让重建动作断在第几步。
工程量级/典型值。⛔ 「有限步」里的那个步数上限不给数——它属平台相关量,取决于工具链的集成程度(工具之间能不能互相引用标识、能不能一键取回),须由本项目定;⛔ 也不得写成「一般几步之内」这类看起来像区间的表述,那仍然是给数。本条能给的是两样:四样必须拿得出来的东西,以及「哪一步走不通、哪里就是真缺口」这条定位法。
易错点。两个,而且都会让这次演练白做。① 把演练做成「查有没有这份文件」——一个人拿着清单逐项问「配置管理计划有吗」「追溯矩阵有吗」,全部答有,于是判为通过。⚠ 这不是本判据要问的问题。本判据问的是「不靠人的记忆走一遍」:只要有一步需要打电话问某个人(「那次用的是哪一版工具,我去问一下老张」),这一步就是断的,哪怕老张真的记得。② 把演练对象挑成最新的那一版——最新版所有人都记得,工程师能凭记忆把每一项都答上来,于是每一步看起来都通。⇒ 要挑一个半年前就已经发出去的软件件来演练才有意义:那时的经手人可能已经换岗,记忆已经不可用,剩下的才是这套机制本身的能力。
1.4 配置项全集:沿「我们组写出来的文件」去数,漏的不是一条,是六整类
是什么。「哪些东西必须纳入配置管理」是一个全集问题,而全集问题必须先回答一句:我是沿什么线索在数的?绝大多数人默认沿的线索是「软件开发过程中我们组写出来的文件」。这条线索问的其实是「我们组产出了什么」,它只数得出署我们名字的东西:需求文档、模型、生成代码与手写代码、标定数据集、测试用例与测试报告。这五项确实都要纳管,但它们不构成全集。
不在这条线索上、却同属这个集合的,有六整类——它们的划分依据是「它以什么身份影响交付件」(决定输出 / 描述 / 证据 / 环境 / 下游消费 / 外部输入),⛔ 不按文件类型或存放位置划分:
| 类 | 它是什么 | 例子 | 内容本体的去向 |
|---|---|---|---|
| ① 不是我们写的、却决定输出的 | 换一版,同一份输入产出的东西就不同 | 代码生成器与其配置集、编译器与链接器版本及选项、链接脚本、静态分析工具与规则集、第三方库、基础软件与微控制器抽象层版本、构件配置描述文件与运行时环境生成配置 | 构件配置见 K4-01 热管理嵌入式软件架构与 AUTOSAR 基础、代码生成配置见 K4-02 基于模型开发(MBD):Simulink 建模与代码生成 |
| ② 描述件而不是实现件 | 它描述行为,不实现行为,但下游靠它读懂这台车 | 诊断描述文件、通信矩阵、DID 与 DTC 清单、标定描述文件、刷写序列与刷写驱动 | 诊断侧见 K5-01 OBD/UDS 诊断与故障码(DTC)设计、标定文件库侧见 K6-05 标定数据管理与版本控制 |
| ③ 只在过程里存在、却被过程评估当作工作产物的证据 | 它证明某个活动真的发生过 | 评审记录、追溯矩阵本身、变更请求记录、覆盖率报告、静态分析的偏离与豁免记录、安全分析工作产物 | 覆盖率定义见 K4-03 MIL/SIL/HIL 验证流程 |
| ④ 构建与环境 | 它决定「在哪台机器上、用什么姿势」产出交付件 | 构建脚本、持续集成流水线定义、构建机镜像或容器、许可证服务配置 | 本课射程内(纳管与基线归属) |
| ⑤ 发布之后下游要用的件 | 它出厂后被产线与售后消费 | 变型矩阵表、可写配置字定义、下线写入序列、售后码表、诊断仪数据库版本 | 产线写入与错写拦截见 K6-09 产线下线与售后标定:工位项清单、配置写入与学习值管理 |
| ⑥ 别人交给我们的 | 它是外部输入,却决定最终交付件 | 供应商交付的目标码 / 受保护模型 / 功能模型单元 / 软件构件与描述文件,随件的可标定量清单与授权等级,联合验证与分工表 | 交付形态谱与签署见 K4-09 热管理控制软件的跨企业交付边界:交付物形态、DIA/SEooC、权限分级与联合验证签署 |
⛔ 还有一整块不在本课射程内,说在前面免得白找:仿真侧资产(仿真模型、网格、求解设置、物性表、后处理脚本)的配置管理整块归 J7-07 仿真任务的输入、交付与模型资产管理,本课一个字不讲。⚠ 上表右栏一律只给去向:本课交的是「这些件该不该纳管、归哪条基线」,不是「这些件的内容本体怎么写」。
为什么。沿单一线索枚举时,漏掉的从来不是「少了一条」,而是整类不出现——而这正是它危险的地方:清单看起来是完整的,每一类里的条目都很齐,只是整整六个抽屉从来没被打开过。过程评估里那条「工具链版本没纳入配置项」的典型掉分点,成因就是这个:它从来不在任何一张「我们组的文件清单」上,没有人是故意漏掉它的。⇒ 所以本课要求的动作不是「把清单写细」,而是换线索再数一遍:先写明我沿的是哪条线索,再逐类问「不在这条线索上、却同属这个集合的,还有什么」。
下面把其中四类里最容易出事的四件,各自展开讲透。
(a)工具链必须纳入配置项,判据就是可重建性;而它还有一个特殊性——它的变更根本不经过需求这条通道。把工具链纳管这件事,不必当成一条要背的规矩,它就是 1.2 那条判据的一次直接应用:换一版代码生成器,同一份模型吐出的 C 代码不同;换一个优化等级,同一份 C 代码产出的目标码不同 ⇒ 拿掉它,重建箭头就断。真正需要额外讲的是它的第二重特殊性:工具链的变更是外部推来的(供应商发新版、安全补丁、许可证到期、操作系统升级),它不经过需求文档,因此如果工具链不在配置项清单里,这类变更连触发一次变更请求的入口都没有——不是流程没被执行,是这条通道压根没有入口。这个断掉的入口,第 4 讲会专门画出来。⛔ 本课不写任何具体的工具版本号或产品版本示例:写了就等于把某一个项目的选择当成通例,而平台相关的选择须由本项目确定、禁止抄上一代。⚠ 本课在工具一栏点到的产品名(代码与模型的版本控制工具、配置管理平台、需求管理与追溯工具、变更请求流程工具)一律是示例,不是选型建议。本课只给一条要求:必须记到能复现的粒度,即含配置集与编译、链接选项,⛔ 不只是主版本号。易错点三个:只记工具的大版本而不记配置集与优化等级(同一版工具换个优化等级,产出的目标码不同);把构建机的环境当成理所当然(许可证服务、系统库、路径依赖,换一台机器就复现不出来);把工具链升级当成「基础设施维护」而不是一次需要做影响分析的变更。
(b)诊断描述文件与 DTC 清单必须纳管,并与软件同批发布——它有双重身份。对内,它是软件实现的一部分:哪些故障会置位、置位条件是什么、置位后怎么表现,这些是软件行为。对外,它是诊断仪与售后数据库读懂这台车的字典:车上置出的一个码,售后端能不能把它翻译成「多通阀位置反馈超差」而不是别的什么,取决于两侧用的是不是同一版。⇒ 只要两侧对不上,车上的码在售后端就是失明的:要么读不出来,要么被解读成另一个故障,而后者比前者更坏(它会把维修引到错误的方向)。⚠ 这类问题有一个极不利的性质:它在整车验证阶段完全不出现——验证台架用的就是同一批文件,两侧天然对齐;它只在售后端第一次暴露,而那时车已经在用户手里。⛔ 本课不给 DTC 条数,不写诊断服务的请求响应格式与否定响应码,也不写会话与安全访问前提——服务与 DTC 机制的本体由 K5-01 OBD/UDS 诊断与故障码(DTC)设计 承接;本课只管这一类件作为配置项被纳管、与软件版本对齐、并随发布件一起发出去。易错点三个:把诊断描述文件当成「诊断工程师的文件」而不进软件基线;DTC 语义改变但编号没变时不更新描述文件与售后码表——编号没变,所以从台账上看什么都没发生,这是最难查的一种;只更新了描述文件而没有通知售后端更新诊断仪数据库(文件对了,但对齐这件事没有传导到下游)。
(c)测试件(测试规程、结果记录、覆盖率报告)必须进基线——证据不带版本标识,就等于没有证据。双向追溯要求两个方向都走得通:正向是「一条需求能走到它的验证证据」,反向是「一份证据能走回它服务的需求」。反向这一半在缺少标识时根本走不通:手上一份覆盖率报告,如果它不写明对应哪条基线、哪个软件版本、哪份标定数据集、哪套工具与台架配置,它就无法证明自己对应的是现在这一版代码——它可能是三个月前那一版跑出来的,而没有任何东西能否证。⇒ 所以测试件不是「跑完就归档的材料」,它是配置项,必须携带上面那组最小标识。⚠ 与外部体系的对应关系放在这里说一次,但只说到过程域这一层:基线与配置项对应 SUP.8(配置管理)、变更请求与影响分析对应 SUP.10(变更请求管理)、需求追溯对应 SWE.1、验证与测试工作产物对应 SWE.4~SWE.6。⛔ 本课不写任何基本实践条文、工作产物编号与能力等级判据。★ 并且必须写明一件事:该过程参考与评估模型有 3.1 与 4.0 两版并行流通,后一版调整过过程域名称与工作产物编号 ⇒ 引用时必须显式声明所依版本,⛔ 不得混引、⛔ 不得单值化;完整的产出物与过程域对应、以及「过程评估到底在看什么」,第 6 讲收口。⛔ 覆盖率的定义、验证层级(单元 / 集成 / 合格性)与在环形态的选择由 K4-03 MIL/SIL/HIL 验证流程 承接,本课不给任何覆盖率目标值。易错点三个:报告归档了但不带基线号;测试用例没随需求变更更新(这既是一条典型掉分点,也是追溯链「代码到测试」那一处的断点);把「跑过了」当成证据,而没有可复现的结果记录。
(d)「需求」这个配置对象,在控制域里的实际载体是控制功能规格文档。抽象地说「需求要纳管」没有可操作性,得落到本领域的具体载体上。⇒ 本课对它划一条很窄的边界:本课管它作为配置项怎么被冻结、被引用、被追溯;⛔ 不管它怎么写、字段怎么定、评审怎么组织、写到什么粒度、冻结时点怎么选、什么样的条款改动才算触发一次变更请求——后面这一整串由 K4-07 热管理控制功能规格(软件需求)的编写、评审与向 Tier1 交接 承接。为什么要把界划得这么死:不划,本课与 K4-07 热管理控制功能规格(软件需求)的编写、评审与向 Tier1 交接 必然重叠,而重叠的后果不是浪费,是两门课各给一套口径、读者不知道听谁的。⛔ 本课不给条款粒度、不给字段模板、不给评审检查表,一律标去向。易错点两个:把需求管理工具里的条目当成需求本身而忽略了它的基线——工具里的条目是活的,基线是死的,追溯关系要指向后者,指向活条目的追溯在条目被改后会悄无声息地失效;以及需求改了却只在工具里改,没有触发下游模型与测试用例的重新评审,追溯链在第一环就断掉。
1.5 「能追溯」不是「有一张追溯表」,是双向都走得通、每一环都交得出证据
是什么。「追溯」这个词在项目里被用得极松,松到「我们有一张追溯矩阵」就可以算做到了。本课给它一个操作化定义,即用一个可以执行的动作来定义它,而不是用一份制品来定义它:
- 正向:从一条需求出发,能走到它的模型、它的代码、它的测试用例、以及它的测试结果,每一步都指得出具体是哪一份、哪一版。
- 反向:从一次提交、一个测试结果、一个现场故障出发,能走回它服务的是哪几条需求。
- 并且:每一环都交得出证据——不是「表上填了」,是那一环指向的东西真的存在、带着版本标识、能被取回来。
⇒ 三条缺一不可。只有正向、没有反向的追溯,在正常开发里毫无感觉,在出事那一天彻底失效:一个现场故障拿回来,你想问「它违反了哪一条需求、这条需求当初是怎么验证通过的」,反向走不通就问不出来。⚠ 而过程评估里扣分最多的,恰恰是反向那一半——因为只沿「需求→设计→实现→验证」这条单向线索去建追溯,反向那一半整类不会出现。
八个高发断点。把「追溯做得好不好」这个模糊问题,换成八个可以逐个检查的位置:
| # | 断点 | 典型表现 |
|---|---|---|
| 1 | 需求 → 模型 | 需求改了,模型没跟 |
| 2 | 模型 → 代码 | 手改生成代码(改完之后模型与代码不再是同一个东西,而重新生成一次会把手改抹掉) |
| 3 | 代码 → 测试 | 测试用例没随需求变更更新,测的还是老行为 |
| 4 | 测试 → 证据 | 跑过但报告没归档,或报告不带基线号与软件版本标识 |
| 5 | 变更请求 → 提交 | 提交信息不带变更请求号 ⇒ 变更记录与实际提交对不上 |
| 6 | 分支 → 主干 | 紧急修复只在发布分支上改完就发,未合回主干,下一个常规版本又把这个缺陷带回来 |
| 7 | 配置项 → 工具 | 工具链版本与配置没记 ⇒ 重建不出同一份代码 |
| 8 | 离线件 → 车端 | 车上读不回软件版本与标定版本,或读回来与刷写文件里的版本块对不上(怎么读回、落在哪些标识符上,第 6 讲交代) |
★ 每一个断点恰好对应过程评估的一个典型掉分点,这不是巧合——评估看的就是这条链走不走得通。⚠ 断点编号只用于正文与图上的相互引用,⛔ 它不表示严重程度排序。第 6 讲会把六条典型掉分点逐条挂回这张链上,并说清每一条让 1.3 那个重建动作断在第几步。
追溯覆盖率,以及它唯一真正的争议处。把追溯的完整度量化,常用的定义式是:
追溯覆盖率 = 已建立追溯关系的需求数 / 总需求数
这个式子本身没有什么可讲的(它是定义,不是实测值)。真正要讲透的是分母的口径:分母到底算不算已注销的需求、已推迟到下一阶段的需求、非功能需求、继承自平台而本项目未再评审的需求?这四类每纳入或剔除一类,同一批追溯关系算出来的比值就会明显不同,而报表上的读数长得一模一样。⇒ 结论是硬的:分母口径不写死,这个比值可以被调成任何想要的数;⛔ 没有写明口径的追溯覆盖率,不许拿去与任何别的数比较——不同项目之间不行,同一项目的不同阶段之间也不行。这是「单位或基准自带口径的量必须写明本项目取哪一套」这条通则的一次直接兑现。
工程量级/典型值。本条能给的只有定义式本身与分母口径这一问。⛔ 追溯覆盖率的目标值不给数——它取决于本项目所依过程模型的评估等级目标与内部规定,须由项目定;⛔ 也不得写成「一般要求达到较高水平」这类看起来像区间的说法,那仍然是给数。⛔ 正文、图、图注与图的替代文字四处一律不给这个目标值。
易错点。三个。① 把追溯矩阵做成一张评审前突击填的表——填出来的是覆盖率,不是追溯:追溯关系应当在建模、写代码、写用例的那一刻就被记下来,事后补是一次考古(人反过来猜「当初这个子系统是为了哪一条需求」),猜出来的对应关系没有任何证据力。② 只做正向——读者很容易觉得「我从需求能找到测试用例,追溯就通了」,而上面说过,反向走不通时,一次现场故障根本定位不到它违反了哪条需求。③ 把覆盖率当成目标去凑——把追溯关系批量挂上去,正向查得到、反向全是错的,这个数越好看越危险,因为它会让人停止追问。
1.6 与机械件图纸的类比只成立到一半,而不成立的那一半正好是全部难点
是什么。给机械背景的同事解释「软件为什么要管版本」,最好用的一句话是「跟图纸版本管理一样」。这个类比成立的那一半确实很有力:图纸要有版本标识、要有变更记录、要有发放与回收、改动要评审——软件一样。⚠ 但它不成立的那一半必须当场点破,否则读者会把图纸那套做法原样搬过来。三处结构差异:
| 属性 | 机械件图纸 | 软件 |
|---|---|---|
| 版本拓扑 | 线性:一版接一版,前后关系明确 | 有分叉与合并:同一时刻存在多条并行的线,还会重新合到一起 |
| 副本数 | 单一权威副本:受控发放,谁手上那一份是不是最新的可以查 | 多副本并存:每个人的工作副本都是完整的一份,各自都能改、都能编译、都能跑 |
| 依赖可见性 | 画在图上:材料、热处理、配合件、基准,看图就知道它依赖什么 | 不写在文件里:工具链、第三方库与基础软件、构建与链接选项,全部不在源文件里写着 |
★ 这三处差异不是「软件更复杂」这句空话的三种说法,它们各自对应一条具体的做法失效。
为什么。逐条看它们各自打掉了图纸做法里的哪一条。版本拓扑不同 ⇒ 「版本号大的就是新的」这条直觉失效:分叉之后,两条线上的软件版本号不可跨分支比大小(这也正是第 2 讲要给版本号挂分支标识的原因)。副本数不同 ⇒ 「受控发放、回收旧版」这套动作没有对应物:软件的副本是复制出来的、不受控的,你无法「回收」谁本地那一份。依赖可见性不同 ⇒ 这是最要命的一条:图纸拿到手,它依赖什么写在图框与技术要求里;而一份源代码拿到手,它依赖哪一版代码生成器、哪一版编译器、哪个优化等级、哪一版基础软件,文件里一个字都没有。⇒ 于是「把文件存好」这件事在机械侧几乎等价于「把依赖存好」,在软件侧则完全不等价——这正是 1.2 那条判据要求把工具链、构建与环境整类纳管的根本原因。
工程量级/典型值。⛔ 本条不给任何数:分支条数、并存副本数、依赖项个数都不给,它们既属平台相关量,也与本条的论点无关。本条给的全部是三处结构差异本身。
易错点。两个,而且都是「把类比用过头」的产物。① 沿用图纸思维要求「只能有一份最新版」——听起来是纪律严明,实际后果是特性开发无处落脚:一个要开发两周才能跑通的功能,中途每一天的中间状态都不允许存在于受控的地方,于是人开始在本地各改各的、谁也看不见谁,情况比允许分支时更糟。正确的做法不是禁止多副本,而是规定它们怎么隔离、怎么合回来——这正是第 2 讲分支策略要讲的东西。② 以为「用了版本控制工具就等于做了配置管理」——⚠ 这是本讲最需要点破的一句话。版本控制工具管的是文件的历史:谁在什么时候改了哪一行,它做得非常好。而配置管理管的是元组的一致性:这一份代码、这一版模型、这一份标定数据集、这一套工具链、这一批测试证据,在某一刻被同时钉住并可被重建。⇒ 后者工具不会自动帮你做:一个代码仓库的标签只钉住了代码那一条泳道,它对标定数据集与工具链一无所知。
⇒ 本讲到此把「为什么要管、管什么、怎么算管住了」三件事交代完了:机制层判据是基线元组与可重建性(1.2),工程层判据是不靠人的记忆重建一遍(1.3),管的对象是六类线索之外补全的配置项全集(1.4),「管住了」的操作化定义是双向追溯、八个断点(1.5),而它不能照搬图纸那一套(1.6)。⇒ 第 2 讲接着往下走一层,处理三件具体的工程手段:软件版本号方案怎么切才能回答「下游要不要跟着改」、分支与合并怎么组织才能回答「这一版到底包含什么」、以及基线那条横切线到底该在什么时点落下去。
后面还有 5 讲正文 · 关键公式 · 案例拆解 · 常见误区 · 动手做