软件构建(十三)——代码集成

集成是指将一些独立的软件组件组合为一个完整系统。对大项目,集成也许要花数周或数月时间,把一组程序编织为一个整体。本文将首先介绍不太常用的阶段式集成,然后再介绍更为常用的增量集成,其中集成的策略是讨论的重点。最后每日构建与冒烟测试的使用原则。

集成是在开发人员完成开发者测试之后才进行的,而且集成过程是与系统测试一道进行的,所以集成有时也被认为是一种测试行为。然而,集成本身就足够复杂了,因此应该被看做一项独立的行动。程序集成有两种方式:阶段式集成和增量集成。

1. 阶段式集成

  1. 设计、编码、测试、调试各个类,这一步称为“单元开发”
  2. 将这些类组合为一个庞大的系统,这一步成为“系统集成”
  3. 测试并调试整个系统,这一步成为“系统瓦解(system dis-integration)”

这种集成的问题是,当第一次把系统中的类放到一起时,新的问题会不可避免地大量浮现,所有的类都有嫌疑导致出问题的位置难以确定。所以对绝大多数情况,阶段式集成都不是很适用。

2. 增量集成

2.1 方法

  1. 开发一个小的系统功能部件。它可能是最小的功能部件、最难的部件、关键部件、或者以上的某种组合,对它彻底地测试并调试。将它作为骨架,稍后附着肌肉、神经、皮肤等系统的其余部件
  2. 设计、编码、测试、调试某个类
  3. 将这个新的类集成到系统骨架上,测试并调试“骨架和新类的结合体”。在进一步添加任何新类之前,确保该结合体能工作。如果做完了剩余的所有工作,就回到步骤2开始重复这一过程

2.2 相对阶段式集成的优势

  • 易于定位错误:降低“多个问题之间相互影响”或“一个问题将另一个问题掩盖”的风险
  • 及旱在项目里取得系统级的成果
  • 改善对进度的监控:利于管理层判断进度和需求
  • 更加充分地测试系统中的各个单元
  • 能在更短的开发进度计划内建造出整个系统

2.3 策略

  • 自顶向下集成
    • 一般从主入口(Main函数、主窗体等等)开始,测试顶层类时需要一些存根(stub)类辅助,最终逐渐替换为实际的类
    • 优点:能快速得到一个能部分工作的系统,并及早地暴露一些设计上的问题
    • 缺点:棘手的系统接口的演练必须留到最后才进行,有问题的底层可能会反过来影响顶层
    • 纯粹的自顶向下集成几乎是不可能的,大多时候使用混合方法集成,或用下图的在各个竖直划分的功能块中自顶向下集成

在各个竖直划分的功能块中自顶向下集成

  • 自底向上集成
    • 首先要完成整个系统的设计,然后一个一个添加底层类向上层集成,最初需要编写驱动测试类
    • 优点:容易定位错误,尽早演练“可能存在问题的系统接口”
    • 缺点:如果高层存在概念上的设计问题,那么要把所有细节工作都做完才能发现
    • 一般也很少用纯粹的自底向上集成
  • 三明治集成
    • 首先集成继承体系顶部的高层业务对象类,然后集成底部的与设备接口的类和广泛使用的工具类,最后集成中间层的类
    • 结合了上述两种方式的优点,是现实的实用的方法
  • 风险导向的集成
    • 大顺序和三明治集成一致,但细节顺序,是优先考虑高风险的实现最有挑战的部件,如顶层接口、底层系统接口、未被透彻理解的算法的类等等
  • 功能导向的集成
    • 首先需要搭建好骨架,然后按照功能(模块)划分顺序来集成,如下图所示

功能导向的集成示意图

  • T型集成
    • 先选中某个特定的“竖直块”及早开发并集成,这个功能块应该能从头到尾演练系统,并找出系统设计的全部主要问题。纠正所有问题后,就可以开始开发系统其它核心部件,如下图所示。这种方法常与风险导向和功能导向集成集合使用

T型集成示意图

集成顺序的策略有多种多样的形状和规模,没有哪一种对所有情况而言都是最佳的。最佳集成步骤随项目不同而变化,最佳解决方案总是为了满足特定项目的特定需求而制定的,不要像教条一样遵循前面提到的任何过程。

3. 每日构建与冒烟测试

无论选用哪种集成策略,每日构建(daily build)冒烟测试都是软件集成的好方法。这些简单的过程可以降低出现低质量软件的风险,也便于诊断缺陷,并且每天的成果可以极大地鼓舞士气。以下是这两种方法的一些使用原则:

  • 关键是每一天坚持build:某次build失败可以将错误锁定在一天之内
  • 检查失败的build:每个项目要建立一套评定“什么才算是破坏了build”的质量标准
  • 每天进行准确的冒烟测试:冒烟测试应彻底地从头到尾演练已完成的系统的主要功能,不要认为是浪费时间的重复性工作
  • 自动化:脱离自动化谈每日构建与冒烟测试是不切实际的
  • 成立build小组
  • 仅当有意义时,才将修订(revisions)加入build中……:因为通常开发者编写代码的速度不会快到使系统每天都有明显的进展
  • ……但是别等太久才将修订加入进来:警惕某个开发人员接连两三天都不check in他做的改动,他很可能陷入一组牵扯到大量文件的修订中
  • 要求开发人员在把他的代码添加到系统之前,进行本地冒烟测试
  • 为即将添加到build的代码准备一块暂存区,在暂存区产生新的build并认为其可接受时,才合并到主源码中
  • 惩罚破坏build的人:build失败是异常情况,应严肃对待
  • 在早上发布build:测试人员可以当天测试,发现问题也能尽早找到开发者解决
  • 即使有进度压力,也要保持daily build和冒烟测试

参考文献:电子工业出版社《代码大全(第2版)》第29章

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器