Table of Contents
关键系统下行时间的高昂成本
在航空航天、能源、交通和医疗等部门,软件故障不仅仅是不便 — — 可能导致灾难性后果。 比如,2015年纽约证券交易所的停业导致数百万人失去交易,而医院输液泵中的软件故障可能危及病人的生命。 即使是关键工程系统短暂的停工时间也会导致安全隐患、监管处罚和声誉受损。 重新制定 — — 重组代码而不改变外部行为 — — 是一种纪律性的方法,可以减少技术债务,提高系统的复原力,但必须精确实施,以避免引入新的风险。
尽量减少下行时间的核心重构原则
在任务关键环境下有效重构基于三个支柱:行为保全, 递增变化[,以及 防御测试[].行为保全确保每个重构步骤使系统可观察到的输出都相同. 递增改变限制任何单一修改的爆炸半径. 防御测试验证每个步骤没有发生倒退. 遵循这些原则,降低了在重构期间和之后的倒置概率.
安全重建关键战略
平行运行和阴影模式
在阴影模式下,重构组件会与原始系统并列运行,处理相同的输入,但静默地丢弃输出。工程师们比较结果以检测差异而不影响活操作。一旦信心高,阴影组件可以提升到初级状态。这一技术对于核心算法或数据处理管道特别有用,因为正确性至高无上。
特性切换
特性切换(或旗帜)允许您将重构代码包裹在配置切换器后面。重构路径在明确打开之前仍然不活动,使团队有能力在出现问题时逐渐或立即滚回。在关键系统中,切换器应该是静态的(部署时设置),而不是动态的,以避免运行时变化导致的意外行为。
加那利语的释放
金丝雀释放会引导一小部分流量流向重构系统,而大多数则在稳定版本上继续运行. 这种方法在生产负荷下提供现实世界验证. 如果金丝雀显示错误率或耐久性较高,可以立即调整流量,对于控制物理设备的工程软件,金丝雀释放可能需要专门的测试环境,以镜像生产,但与现场操作隔绝.
蓝绿色部署
蓝绿色部署维持着两个相同的环境:“蓝” (当前稳定)和“绿” (重构 ) 。 在对绿色环境进行彻底验证后,在单一原子操作中,交通从蓝色转向绿色。 如果出现问题,则同样迅速地转换为蓝色。 这一策略对无国籍应用有效,可以适用于状态良好的系统,同时进行仔细的数据同步。
计划维护窗口
尽管做出了最大努力,但某些重构程序无法透明地引入。在这种情况下,在设定的维护窗口中,最好在系统负载最低时,修改时间表。将窗口明确告知利害关系方,并确保重排程序并记录在案。在高峰运行期间或紧接关键最后期限之前,绝不部署重构程序。
建造一条强大的测试管道
单位和综合测试
综合测试套件对于关键系统是不可谈判的. 单元测试验证单个功能,而集成测试则确认重构模块与现有组件的正确交互. 使用测试覆盖工具以识别未经测试的代码路径. 对于安全关键软件,考虑正式核实[或基于模型的测试[以数学方式证明行为不变. Martin Fowler网站的重构目录提供了必须经过测试支持的行为保留转换的经典实例.
回归测试和连续整合
每一个承诺捕获错误的自动回归测试很早就进行。 连续集成( CI) 管道应该在分钟内执行完整的回归套件。 对于关键系统, 还要运行 [[FLT: 0]] 性能回归测试[[[FLT: 1]] 以确保再集成不会降低时间或资源使用。 [[FLT: 2] 递归测试套件[ 维护至关重要—— 当你修复一个错误时, 在重集时, 添加一个复制该程序的测试。
恢复能力验证的混沌工程
混沌工程故意将故障注入系统以观察其在压力下的行为。应用到重构组件中,可以揭示重组中引入的已改变或新故障模式的假设。 混沌工程[ 等工具可以模拟网络分割,资源耗尽或交通突然暴动。Netflix和亚马逊等组织已经采用了这一学科,以确保无法承受故障时间的系统具有弹性。
关键系统重构的执行步骤
评估和规划
首先要彻底分析系统架构。 找出定义明确、测试范围高、与安全关键路径隔绝的模块。 使用 依赖性图表来理解影响。 排名重构候选人的风险和商业价值。 请域专家—— 了解硬件限制、操作条件和监管要求的工程师—— 来验证计划。
版本控制和回滚
每次重构更改都必须被承诺在一个单独的分支中进行,并带有清晰的下划线信息来描述转换。在工作开始前标记稳定的释放。回滚计划不仅应当详细列出代码返回,而且应当详细列出必须取消的数据库迁移或配置更改。在中转环境中执行回滚程序,以便在事件发生时成为第二性质。
扭曲环境
以硬件、网络地形和数据量来反映生产的中继环境对于安全重构至关重要。 在此运行完整的测试套件和性能基准。 对于与物理机械(例如机器人控制器、电网显示器)接口的软件,中继环境应包括复制真实世界输入和输出的模拟循环。 只有在中继程序通过所有标准后,更改才能转移到生产。
监测和观察
重构后监测必须跟踪功能正确性和操作健康性。 设置 [[FLT: 0]] 缓存 [[FLT: 1] 以备误速率突升、 缓存增加和资源消耗变化。 使用分布式跟踪跟踪以通过重构代码路径跟踪请求。 在关键系统中, 不仅监测软件, 而且还监测任何连接的硬件, 用于异常。 维护一个仪表板, 用于比较至少一个周期正常运行的重构前和后计量标准 。
关键代码通用重构技术
并非所有的再造技术都同样安全。
- Extract Mode – 将一组代码移入一种新方法来提高可读性. 保证提取的方法不会增加副作用.
- 重命名变量或函数[ – 在不改变执行的情况下提高清晰度。使用 IDE 支持的重命名来捕捉所有引用 。
- 将魔法编号换成符号常数 – 消除在维护过程中可能造成混乱的硬码字元.
- 简化条件表达式 – 将复杂的如果-else级联拆分为守护条款或切换语句,但需经过所有分支的彻底测试后才能进行.
- 引入参数对象 – 将相关参数组合成单个对象以减少方法签名复杂度.
每种技术都必须在下个技术之前单独应用、测试和投入。 软件改进小组关于重构安全关键系统的白皮书 提供了为高可靠性环境选择正确方法的实用指导。
减少风险和治理
代码审查和对等编程
每一个重构承诺都必须至少由熟悉系统的两位工程师来审查。 在重构过程中对等编程可以防止小错,促进知识的转移。 审查应当侧重于行为保护、测试覆盖和重构计划的遵守。
专家验证
在关键领域,涉及能够理解软件编码的物理、化学或操作逻辑的主题专家。 中小企业可能会发现,一个被重新命名的变量现在与该领域广泛使用的缩写发生冲突,或者一种提取的方法无意中按照对时间敏感的顺序重新排序。
变动咨询委员会
对于属于更大认证系统的软件(如航空,核反应堆控制),任何代码更改都可能需要变更控制委员会的核准. 董事会审查重构计划,风险评估,回滚策略,以及验证证据. 将重构原理和测试结果以符合行业标准的格式(如DO-178C,IEC 61508)记录下来,确保了审计的可性.
结论
重构本身不是目的 — — 这是保证关键工程软件安全、可维护、有弹性的手段。 通过应用渐进式变化、严格的测试和部署策略来将风险降至最低,工程师可以减少技术债务而不会造成故障。 关键在于用与安全关键环境任何其他变化相同的纪律来对待重构:彻底计划、强迫测试,并始终有回滚准备。 完成后,重新铸造脆性代码,而不中断社会所依赖的系统。