• 《持续集成:软件质量改进和风险降低之道》


    持续集成:软件质量改进和风险降低之道

    主旨

    这本书讲的是关于持续集成的原则和实践。Martin Fowler关于CI的热门文章发表于2006年,这本书作于2007年,虽然十年间CI的工具已经发生了不少变迁,但本书中提到的基本原则和实践仍然值得借鉴,而且书中提到的关于CI未来发展方向的论述也得到了验证。

    本书分为两部分:

    • 第1部分:CI的背景知识,包括基本概念、基本原则与推荐的实践
    • 第2部分:如何创建全功能的CI系统,包括五个持续:
      • 持续数据库集成
      • 持续测试
      • 持续审查
      • 持续部署
      • 持续反馈

    第1部分 CI的背景知识

    什么是持续集成

    Martin Fowler在其文章中将CI描述为:

    一种软件开发实践,即团队的成员经常集成他们的工作,通常每个成员每天至少集成一次——这导致每天发生多次集成。每次集成都通过自动化的构建(包括测试)来验证,从而尽快地检测出集成错误。许多团队发现,这个过程会大大减少集成问题,让团队能够更快地开发出一致的软件。

    这意味着持续集成其实是一系列实践的集合,例如:

    • 所有开发者均先执行个人构建,在将代码提交到代码库中,以保证集成构建不会失败
    • 开发者每天至少向代码库提交一次代码
    • 集成构建每天会在一台独立的机器上执行多次
    • 每次构建必须100%通过测试
    • 构建必须有产物,如可部署的包等
    • 修复失败的构建是最高优先级的事情
    • 构建中包含代码复查,生成如代码质量报告或依赖分析报告等,作为改进的参考

    关于CI:

    • CI实践中提倡自动化,因为集成本身就是一个需要多次重复的过程,自动化有利于降低出错的可能性
    • 使用CI的一个明显好处是能够得到快速反馈,这与重构、TDD等实践的理念是一致的,即进行小的变更,而CI为这些变更提供了一张安全网
    • 关于“持续”一词的解读,其实更应理解为“经常”集成

    引入持续集成

    • 越早引入CI越好。因为越到项目晚期实现CI会越困难,人们迫于压力有可能会拒绝改变。如果不得不在项目晚期开始实现CI,建议先从较小的工作开始,逐渐扩大范围
    • 应该“早集成,常集成”。因此应该经常提交代码,更多的提交通常意味着更小的变更,风险会更小
    • 项目文化中应该将修复失败的构建为最高优先级的事,否则团队中的人就无法继续自己的工作

    利用CI减少风险

    CI不仅仅能帮你节省时间,更能帮你减少项目中的以下风险:

    没有可部署的软件

    出现这种风险的原因可能有:

    • 没有使用独立的机器来负责软件集成
    • 没有将数据库变更通过版本化的脚本管理起来
    • 手工部署软件导致的错误

    很晚才发现缺陷

    出现这种风险的原因可能有:

    • 没有实现自动化的回归测试,仅凭手工没有时间回归所有测试
    • 较低的测试覆盖率

    缺少项目可见性

    出现这种风险的原因可能有:

    • 人工沟通导致信息的丢失与理解偏差
    • 缺乏对软件系统架构或类图的可视化呈现

    低品质的软件

    出现这种风险的原因可能有:

    • 没有遵守编码标准的代码
    • 没有遵守架构标准的设计
    • 重复的代码

    第2部分 如何创建全功能的CI系统

    持续数据库集成

    持续数据库集成(Continuous Database Integration,CDBI)指的是将数据库的变更视为集成的一部分,在每次项目的版本库发生变更时,重建数据库和测试数据库。

    为什么要进行数据库集成自动化?

    因为团队没有赋予个人修改数据库的能力,许多项目中DBA经常成为瓶颈。

    持续数据库集成的推荐实践

    • 将创建数据库、删除数据库、插入数据等任务使用脚本自动化让每个开发者都能够使用简单如db:create式的命令执行
    • 使用不同的SQL文件来支持不同的环境,如开发、QA、生产环境等
    • 每个开发者应该有独享的数据库“沙盒”来隔离代码变更,比如独立的schema,或者独立的数据库
    • 将DBA解放出来研究和完成一些更高级的任务,比如优化数据库的性能、优化SQL的性能、数据规范化等
    • 数据库也有测试工具,如PL/Unit、QUnit、SQLUnit

    持续测试

    为什么要进行持续测试?

    根据系统工程的可靠性定理,线性系统的可靠性是每个系统组件可靠性的乘积,这意味着系统整体的可靠性要低于任一个系统组件的可靠性。更何况考虑到系统组件之间的连接,软件系统应该是一个非线性系统,可靠性比线性系统更低,所以我们必须测试每一个系统组件的可靠性。

    自动化测试的分类

    • 单元测试:对系统中最小的代码单元的测试,这个单元通常是一个类
    • 组件测试:验证系统的各个部分组合到一起能够产生预期的行为,通常通过API来执行
    • 系统测试:验证整个系统的行为是否正确,通常通过外部接口,如web界面或GUI等来进行,可以通过Selenium这样的框架来驱动浏览器执行
    • 功能测试:从客户的角度来验收整个应用程序是否满足所需功能,通过模拟用户行为来执行,通常也被认为是用户验收测试

    持续测试的推荐实践

    • 将不同的开发者测试分类
    • 将自动化的开发者测试提交到代码库中
    • 先执行较快的测试
    • 使用适当的框架,让组件测试可重复

    持续审查

    持续审查是指对代码风格、代码是否符合编码标准的检查,需要通过自动化代码审查和人工审查相结合来进行。

    自动化代码审查是人的智慧的增强,通过诸如PMD、Simian等工具来检查代码的圈复杂度、耦合度等指标,有的还能提示代码中潜在的风险。

    圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准,在1976年由Thomas J. McCabe, Sr. 提出。
    在软件测试的概念里,圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。
     
       

     

    但自动化代码审查并不能检出所偶问题,人工审查仍是必不可少的,人工审查更关注于自动化代码审查检查不出来的东西,比如代码的可读性、可维护性等。

    持续部署

    持续部署的目的是让团队随时随地都可以按需发布能工作的软件,同时使得发布工作量最小。

    部署工作应该简化到只需一条类似ant deploy式的命令即可完成。

    一个典型的部署工作由6大步骤组成:

    1. 为库中的资产打上标签:为版本库中的同一组文件打上标签,表示是与同一个包有关。相当于为包依赖的代码文件做一组快照。
    2. 得到干净的环境:在作者写这本书时docker还没有诞生,所以要得到一个干净的环境,通常需要删除所有已安装的软件甚至重新安装操作系统,所幸的是今天已有容器技术帮助实现应用程序环境之间的隔离,我们可以随时从一个干净的操作系统开始,层层构建所需的依赖。
    3. 为构建版打上标签:这里的构建版标签与第1步中的版本库标签是不同的。版本库标签用来说明一组文件是相关的,是同属于一个版本的;构建版标签用于表示构建出的二进制包是唯一的。
    4. 执行所有的测试:部署前的测试重点是在一个干净的类生产环境下执行所有的测试,包括所有的自动化测试,以及人工检查。尽管自动化测试能够覆盖许多检查项,但人工检查仍是必不可少的,因为软件仍然是由人来使用的产品,人工检查能够检查出一些自动化测试测不出来的问题,比如UI界面方面的问题等。
    5. 创建构建反馈报告:生成本次构建的报告,包括文件变化信息、修复了哪些缺陷、实现了哪些功能等,在团队中共享。
    6. 回滚的能力:如果部署后发现问题,通过构建版标签和版本库标签可以找到想要的版本,快速回滚到前一个构建版,“撤销”部署。

    持续反馈

    CI存在的意义就是为了能够快速构建并让构建快速失败,目的就是为了能够获得快速的反馈信息。

    持续反馈就是在正确的时间,以正确的方式,将正确的信息发送给正确的人。

    CI系统可以利用的反馈机制有邮件、SMS、可视设备、windows任务条、宽屏显示器等。时至今日,还有IM消息这样的方式可供选择。

    CI的未来

    在写作这本书时,人们在CI的实践中经常抱怨:

    • 怎样才能防止失败的构建频繁发生?
    • 怎样才能让构建执行得更快?

    作者期待在将来看到更多的工具能够支持以下功能:

    • 开发者在合入代码前能够先在一台独立的计算机上执行集成构建,即个人构建,成功后才合入代码
    • 并行化方面提供更多功能,或者利用额外的硬件和软件资源来加速构建
  • 相关阅读:
    接口调用实现类&& 为什么Autowired定义在接口上
    getSuperclass与getGenericSuperclass区别
    Error resolving template “pages”, template might not exist or might not be accessible by any of the configured Template Resolver 或者 springboot使用thymeleaf时报html没有结束标签
    dcm4che-core导包失败! mvn pom文件导包总是失败
    使用IDEA springboot 如何通过mybatis-generator自动生成mapper dao model
    《剑指offer》第三十八题:字符串的排列
    《剑指offer》第三十七题:序列化二叉树
    《剑指offer》第三十六题:二叉搜索树与双向链表
    《剑指offer》第三十五题:复杂链表的复制
    《剑指offer》第三十四题:二叉树中和为某一值的路径
  • 原文地址:https://www.cnblogs.com/cx2016/p/12078749.html
Copyright © 2020-2023  润新知