持续交付-发布可靠软件的系统方法 读书笔记

本书讲述如何实现更快、更可靠、低成本的自动化软件交付,描述了如何通过增加反馈,并改进开发人员、测试人员、运维人员和项目经理之间的协作来达到这个目标。本书由三部分组成。第一部分阐述了持续交付背后的一些原则,以及支持这些原则的实践。第二部分是本书的核心,全面讲述了部署流水线。第三部分围绕部署流水线的投入阐述讨论了更多细节,包括增量开发技术、高级版本控制模式,以及基础设施、环境和数据的管理和组织治理。

译者序

  • 本书要解决的问题:软件开发的“最后一公里问题”:如何让软件从“开发完成”迅速实现“上线发布”。

马丁·福勒. 序

马丁·福勒 作品
马丁·福勒. 分析模式—可重用对象模型. Addison-Wesley. ISBN 0-201-89542-0.
马丁·福勒; Kent Beck. 规划极限编程. Addison-Wesley. ISBN 0-201-71091-9.
马丁·福勒. UML精粹—标准对象建模语言简明指南(第三版). Addison-Wesley. ISBN 0-321-19368-7.
马丁·福勒; Kent Beck,John Brant,William Opdyke,and Don Roberts. 重构—改善既有代码的设计. Addison-Wesley. ISBN 0-201-48567-2.
马丁·福勒; David Rice,Matthew Foemmel,Edward Hieatt,Robert Mee,以及Randy Stafford. 企业应用架构模式. Addison-Wesley. ISBN 0-321-12742-0(2003年Jolt生产力大奖).

  • 本书告诉你如何做到无压力且频繁地交付软件

前言

  • 软件发布应该是一个快速且可重复的过程。本书会告诉你如何做到这一点。
  • 从“决定做某种修改”到“该修改结果正式上线”的这段时间称为 周期时间。对任何项目而言,它都是极为重要的度量标准。
  • 创建一个完全自动化、可重复且可靠的过程,让变更顺利经过构建、部署、测试和发布过程。自动化是关键。
  • 本书将讲述如何缩短从想法到商业价值实现的世界,并使之更安全,从而彻底改变软件交付方式
  • 我们的目标是改变软件交付方式,将其由开发人员的手工操作变成一种可靠、可预期、可视化的过程并在很大程度上实现了自动化的流程,而且它要具备易于理解与风险可量化的特点。使用本书所描述的方法,就有可能在几分钟或几个小时内把一个想法变成可交付到生产环境中的工作代码,而且同时还能提高交付软件的质量。
  • 交付成功软件的成本绝大部分都是在首次发布后产生的。这些成本包括技术支持、维护、增加新功能和修复缺陷的成本。
  • 书中描述的所有技术都与交付软件新版本给客户相关,旨在减少时间和降低风险。这些技术的核心是增加反馈,改进负责交付的开发、测试和运维人员之间的协作。

敏捷宣言的第一原则:我们的首要任务是尽早持续交付有价值的软件并让客户满意。

读者对象及本书内容

  • 本书的一个主要目标是改善负责软件交付的相关人员之间的协作,尤其是开发人员、测试人员、系统和数据库管理员以及经理。
  • 本书内容包括经常提到的配置管理、源代码控制、发布计划、审计、符合性和集成,以及构建、测试和部署流程的自动化。也会讲述自动化验收测试、依赖管理、数据库迁移,以及测试和生产环境的创建与管理等技术。将各个方面融合在一起。
  • 我们的目标是提供一个整体方案,并给出这个方案涉及的各种原则。我们认为不会有一刀切的解决方案。本书所述的基本内容可以广泛应用于各种软件项目,包括大的,小的、高技术要求或短平快的快速收益项目。
  • 关注点更多的是通过更好的可视化和更快的反馈改善写作。
  • 每一章都相对独立,可以分开阅读。(建议第一章必读)

精益软件开发运动告诉我们,“整体优化是非常重要的”

内容简介

  • 可以从不同的地方开始阅读
  • 三个部分:1-4章,讲述有规律、可重复、低风险发布的基本原则和与其相关的实践。5-10章,讲述部署流水线。11章开始,深入分析支撑持续交付的生态系统。
  • 第1章必读。其他部分

第一部分——基础篇

  • 描述了理解部署流水线的前提条件。每一章建立在上一章的基础上。
  • 第1~4章
  • 第1章首先描述了在很多软件开发团队常见的反模式,然后阐述了我们的目标以及实现方式。最后总结了软件交付的一些原则,本书的其他内容都以这些原则为基础。

第二部分——部署流水线

  • 详细介绍部署流水线,包括如何实现部署流水线的各种阶段。
  • 第五章~第10章

第三部分——交付生态圈

  • 讨论了用于支撑部署流水线的各类交叉实践与技术

第一章 软件交付的问题

引言

  • 本章要解决的问题:如果有人想到了一个好点子,我们如何以最快的速度将它交付给用户?
  • 专注于构建、部署、测试和发布过程
  • 本书的中心模式是部署流水线。从本质上讲,部署流水线就是指一个应用程序从构建、部署、测试到发布这整个过程的自动化实现。部署流水线的实现对于每个组织都将是不同的,这取决于他们对软件发布的价值流的定义,但其背后的原则是相同的。
  • 部署流水线的目标有三个。首先,它让软件构建、部署、测试和发布过程对所有人可见,促进了合作。其次,它改善了反馈,以便在整个过程中,我们能够更早地发现并解决问题。最后,它使团队能够通过一个完全自动化的过程在任意环境上部署和发布软件的任意版本。
    一个简单的部署流水线

一些常见的发布反模式

下面列出了几种与可靠的发布过程相对应的几种常见的反模式

反模式:手工部署软件
  • 部署应用程序所需的步骤是独立的原子性操作,由某个人或某个小组来分别执行。特征是需要详细部署文档;手工测试;频繁出错;发布时间长(超过几分钟);发布结果不可预测;发布人压力大。
  • 对于那些负责将应用程序部署到开发环境、测试环境或生产环境的人来说,应该只需要做两件事:(1)挑选版本及需要部署的环境,(2)按一下“部署”按钮。对于套装软件的发布来说,还应该有一个创建安装程序的自动化过程。
  • 为什么把自动化部署看做是一个必不可少的目标:
    • 每次手工部署时都会发生错误
    • 既不可重复也不可靠
    • 手动的流程不得不写进文档
    • 自动部署本质上是鼓励协作的
    • 手工部署依赖于部署专家
    • 手工部署枯燥且极具重复性,但仍然需要有相当程度的专业知识
    • 手工部署过程进行测试的唯一手段是重新做一次
    • 每个人都应该使用自动化部署,而且它应该是软件部署的唯一方式
反模式:开发完成之后才向类生产环境部署
  • 应将测试、部署和发布活动也纳入到开发过程中,让他们成为开发流程正常的一部分。
反模式:生产环境的手工配置管理
  • 本书的关键实践之一就是配置管理,其责任之一就是让你能够重复地创建那些你开发的应用程序所依赖的每个基础设施。这意味着操作系统、补丁级别、操作系统配置、应用程序所依赖的其他软件及其配置、基础设施的配置等都应该处于受控状态。
  • 你应该完全掌握生产环境中的任何信息。这意味着生产环境中的每次变更都应该被记录下来,而且做到今后可以查阅。
  • 自动化是关键
  • 变更首先应该被提交到版本控制系统中,然后通过某个自动化过程对生产环境进行更新。
我们能做的更好吗?
  • 软件发布能够也应该成为一个低风险、频繁、廉价、迅速且可预见的过程。

如何实现目标

  • 本书由两个目标,其中之一就是找到减少周期时间(Cycle time)的方法。周期时间是从决定进行变更的时刻开始,包括修正缺陷或增加特性,直至用户可以使用本次变更后的结果。
  • 目标:找到可以以一种高效、快速、可靠的方式交付高质量且有价值的软件的方法。
  • 为了达到目标,我们需要 频繁自动化 地发布软件。
  • 反馈的三个标准
    • 无论什么样的修改都应该触发反馈流程
    • 反馈应该尽快发出
    • 交付团队必须接受反馈,并依据它作出相应的行动
每次修改都应该出发反馈流程
  • 反馈流程:完全以自动化方式尽可能地测试每一次变更。根据系统的不同,测试会有所不同,但通常至少包括下面的测试。
    • 编译通过(语法验证)
    • 单元测试必须成功
    • 一定的质量标准:比如测试覆盖率以及其他与技术相关的度量项
    • 功能验收测试必须成功:业务验收条件
    • 非功能测试必须成功,检查是否满足用户对性能、有效性、安全性等方面的要求
    • 必须通过了探索性测试,并给客户以及部分用户做过演示
必须尽快接受反馈
  • 快速反馈的关键是自动化
  • 对于整个流水线中的提交阶段,其测试应具有如下特征:
    • 运行速度快
    • 尽可能全面,75%左右的代码库覆盖率
    • 测试失败说明应用程序有严重问题
    • 尽可能做到环境中立
交付团队必须接受反馈并作出相应的行动
  • 对于快速交付高质量的软件来说,基于持续改进的过程是非常关键的。
推广
  • 本书的理论与实践可以应用在大型组织中,也可以应用于小团队

收效

  • 主要收益是创建了一个发布流程,这个流程是可重复的、可靠的且可预见的,从而大大缩短了发布周期,使新增功能和缺陷修复能更早与用户见面。
授权团队
  • 部署流水线的一个关键点是,它是一个“拉动(pull)”系统,它使测试人员、运维人员或支持服务人员能够做到自服务,即他们可以自行决定将哪个版本的应用程序部署到哪个环境中。
减少错误
  • 配置信息错误,配置信息都应放在版本控制系统中
缓解压力
  • 压力本身就是问题的根源所在
  • 减少压力的关键在于拥有一个我们前面所描述的的自动化部署过程,并频繁的运行它,当部署失败后还能够快速恢复到原来的状态
部署的灵活性
  • 在一个全新环境上运行应用程序应该是相当简单的事。
  • “只要需要,就可以让软件运行在任何环境中”的能力使我们和客户对我们随时管理所有版本发布过程充满信心。
多加练习,使其完美
  • 最好的策略就是无论部署到什么样的目标环境,都使用相同的部署方法。
  • 只有一种环境可以有多变性,那就是开发环境。

候选发布版本

  • 每次提交代码都可能产生一个可发布的版本

软件交付的原则

为软件的发布创建一个可重复且可靠的过程
  • 几乎将所有的事情自动化
  • 将构建、部署、测试和发布软件所需的东西全部纳入到版本控制管理之中
  • 软件部署包括三件事:
    • 提供并管理你的软件所需要的运行环境:硬件、软件、基础设施以及所需的外部服务
    • 将你的应用程序的正确版本安装在其之上
    • 配置你的应用程序,包括它所需要的任何数据以及状态
将几乎所有事情自动化
  • 自动化是部署流水线的前提条件
把所有的东西都纳入版本控制
  • 需求文档
  • 测试脚本
  • 自动化测试用例
  • 网络配置脚本
  • 部署脚本
  • 数据库创建、升级、回滚和初始化脚本
  • 应用程序所依赖的软件集合的配置脚本、库文件、工具链
  • 技术文档等
提前并频繁地做让你感到痛苦的事
内建质量
  • 越早发现缺陷,修复它们的成本越低
  • 一旦发现缺陷,就要马上着手修复
  • 测试不是一个阶段,不应该开发结束之后才开始
  • 测试也不纯粹或主要是测试人员的领域
“DONE”意味着“已发布”
  • 一件事情的完成与否,并不是一个人能控制得了的,它需要整个交付团队共同来完成
交付过程是每个成员的责任
持续改进
  • 计划,做,研究,行动
  • 如果只在自己所在角色的内部进行反馈环,而不是整个团队范围内进行的话,就必将产生一种“顽疾”:以整体优化为代价的局部优化,最终导致互相指责

配置管理

  • 配置管理是指一个过程,通过该过程,所有与项目相关的产物,以及它们之间的关系都被唯一定义、修改、存储和检索。
  • 配置管理策略将决定如何管理项目中发生的一切变化
  • 决定一个版本控制工具仅仅是制定配置管理策略的第一步而已
  • 假如项目中有良好的配置管理策略,那么你对下列所有问题的回答都应该是“YES”
    • 你能否完全再现你所需要的任何环境吗?(包括操作系统的版本及其补丁级别、网络配置、软件堆栈、以及部署在其上的软件应用及其配置)
    • 你能很轻松地对上述内容进行增量式修改,并将修改部署到任意一种或所有环境中吗?
    • 你能否很容易地看到已被部署到某个具体环境中的某次修改,并能追溯到修改源,知道是谁做的修改,什么时候做的修改吗?
    • 你能满足所有必须遵守的法规吗?
    • 是否每个团队成员都能很容易地得到他们所需要的信息,并进行必要的修改呢?这个配置管理策略是否会妨碍高效交付,导致周期时间增加,反馈减少呢?
  • 本章解决的三个问题:
    • 为管理应用程序的构建、部署、测试和发布过程做好准备。从两个方面解决这个问题:对所有内容进行版本控制;管理依赖关系。
    • 管理应用软件的配置信息。
    • 整个环境的配置管理,这包括应用程序所依赖的软件、硬件和基础设施。另外还有环境管理背后的原则,包括操作系统、应用服务器、数据库和其他商业现货软件。

使用版本控制

  • 版本控制系统的目的有两个:保留每个文件的所有版本的历史信息,并使之易于查找。让分布式团队(空间/时间)可以合作。
  • 目标是能够随时获取软件在整个生命周期中任意时间点的文件状态
  • 高效使用版本控制系统的几点建议:
    • 对所有内容进行版本控制:源代码,测试代码、数据库脚本、构建和部署脚本、文档、库文件和应用软件所用的配置文件;甚至把编译器以及工具集等也放在里面,以便新成员可以很容易的从零开始工作。每个成员都应该将于项目相关的任何文件及其修订状态保存在版本控制存储库之中。
      • 不推荐将源代码编译后得到的二进制文件也纳入版本控制中
    • 频繁提交代码到主干
      • 只有频繁提交代码,你才能享受版本控制所带来的众多好处,比如回滚; 一旦将变更提交到版本控制,那么团队的所有人都能看到这些变更,也能签出它
      • 尽量使用增量方式开发新功能
      • 为保证提交代码不破坏已有的应用程序:(1)提交代码之前运行测试套件;(2)增量式引入变化
    • 使用意义明显的提交注释:
      • 一种注释风格:第一段是简短的总结性描述,接下来的几段描述更多细节。

依赖管理:

  • 外部库文件管理: 建议在本地保存一份外部库的副本;在构建系统中,应该始终指定项目所需外部库的确切版本。
  • 组件管理:构建流水线之间的依赖应该是二进制文件依赖,而不是源文件依赖

软件配置管理:

  • 应该以对待代码的方式来对待你的系统配置,使其受到正确的管理和测试
  • 配置与灵活性:先专注于提供具有高价值且可配置程度较低的功能,然后在真正需要时再添加可配置选项。
  • 配置的分类:
    • 构建时配置:不推荐
    • 打包时配置:不推荐
    • 部署时配置
    • 启动/运行时配置
  • 应用程序的配置管理:
    • 如何描述配置信息:通常为键值对
    • 部署脚本如何存取这些配置信息:数据库、版本控制库、文件目录或注册表;与源代码分离有利于重要信息的安全性 不要把密码签入版本控制系统中,也不要把它硬编码到应用程序中 (如果坚持要将密码存在某处而不是自己记住的话,可以试着把它加密后放在Home目录下)
    • 在环境、应用程序,以及应用程序各版本之间,每个配置信息有什么不同:将那些特定于测试环境或生产环境的实际配置信息存放于与源代码分离的单独代码库中通常是非常必要的,因为这些信息与源代码的变更频率是不同的。而且这种分离方式特别有利于重要信息的安全性,对于这些重要信息(如密码和数字证书等)的存取需要施加限制。

TODO