Practice Agile with TBD


一个小问题的思考

日常的开发和测试工作中,你是否有以下烦恼?

  • 分支生命周期过长,协作开发困难
  • 不敢轻易改动他人的代码,不敢重构
  • 为杂乱无序的提交记录费神,疲于解决提交冲突
  • 不同环境测试的代码具有不确定性
  • 为了保证合并代码不出错,反复进行回归测试

Git为开发和测试提供了一个高效的工具,但往往我们在使用的过程中没有发挥出他最大的潜力,甚至因为使用不当,人为造成不必要的问题。

我们的开发流程是比较标准传统的 GitFlow 分支开发流程:

  1. 研发基于不同的特性拉取不同的 Feature 分支进行代码开发
  2. 开发完成之后,合并到 dev 分支,在开发环境完成联调和自测
  3. 自测完成,合并代码到 qa 分支,由测试开始执行测试用例
  4. 测试通过,合并代码到 release 分支并发布到预发布环境,由测试利用线上数据进行回归测试
  5. 回归完成,合并代码到 master 分支并发布到生产环境,由测试和产品回归和验收产品功能

整个流程涉及4次必要的代码合并和2次必要的回归测试流程。这种情况下,即使回归测试已经比较全面了,是否能保证上线的代码足够可靠呢?

近期我们团队在发布的时候发生了两个小插曲:

  1. 合并代码到 master 分支,没有任何冲突,但发布上线后发现代码错误
  2. 合并代码到 master 分支的过程中,对冲突不够熟悉,选择了错误的代码

这些问题可以通过分支管理规避吗?请往后看。

什么是TBD

Trunk-Based Development 主干开发模式是一种源码管理模型。如它的名字描述那样,开发者大部分时候都在一个被称为 主干 的分支上完成协作。开发者每完成一个任务,即将代码合并到主干分支,以便所有协作者都可以最快同步到最新变更。

与之对应的是 Feature Branch Development 。开发者基于不同的特性构建不同的 feature 分支,在完成目标开发后再合并到主干分支,以完成测试、发布等工作。

FBD FBD

TBD TBD

举一个我们团队中的开发、提测、发布流程为例

FBD FBD 进行三个小功能的开发,其中真正的冲突只存在于F1和F2之间,但FBD的模式形成了6次冲突。其中需要研发人员手动解决的有3次,其余3次虽然可以自动解决冲突,却无法应用fast-forward。因此master、dev和qa分支会存在非常多的因自动合并而形成的提交,影响分支功能的理解。

TBD TBD 冲突只存在于F1和F2,只需解决一次冲突。开发联调、测试和发布,均基于trunk分支本身,或trunk分支的提交构建Tag或Release。trunk分支始终处于非常干净的状态,不会有自动合并产生的无意义提交。

我为什么推荐TBD

Branching is easy, merging is harder.

TBD的初衷是尽量减少代码冲突,提升开发效率和代码的正确性

冲突会带来什么问题?

  • 解决冲突可能导致代码错误
  • 冲突解决后需要测试回归
  • 频繁解决冲突会中断研发同学的工作,降低研发效率
  • 生命周期过长的分支,在解决冲突时需要耗费额外的沟通成本

我们希望:

  • 测试完成工作后,不需要跟研发沟通合并分支、解决冲突等,而是可以自行进入发布流程
  • 所测即所得,不同测试、集成环境只有数据不同,不会存在代码上的差异
  • 分支生命周期足够短,每次合并尽量解决小的、近期开发过的冲突
  • 避免重复工作,同样的冲突解决一次就可以上线
  • 无负担地进行代码重构、升级,而不必担心重构带来的冲突和正确性问题

TBD的优势:

  • 合作者可以在较短时间内同步到最新代码,减少不必要的差异,在3-5人的敏捷团队,表现更佳
  • 研发人员不必花费额外的精力和重复工作去介入测试、发布等工作(如合并feature到master)
  • 研发和测试工作隔离,工作记录通过代码提交即可反应,节约沟通成本
  • 代码提交记录干净清晰,可以快速明确每次提交的内容
  • 即使使用feature的分支开发,其生命周期也较短,有利于减少冲突

TBD的劣势:

  • 提交的代码应该是可上线的,这对研发和测试都是一个挑战
  • 要求较高的代码质量管控,包括代码审核和完整的单元测试
  • Trunk分支和FBD模式的Master分支相比,具有更低的稳定性

TBD和敏捷有什么关系

敏捷致力于使团队以小而可行的增量形成轻量级交付。通过需求评审、工作计划、结果交付,这些流程的持续进行,使得团队可以快速应对变化。

敏捷的特点:

  • 小而美
  • 增量可行
  • 持续集成
  • 持续交付
  • 多做计划
  • 快速迭代
  • 拥抱变化

TBD的特点:

  • 轻量提交
  • 快速合并
  • 持续集成
  • 测试驱动
  • 实时反馈

持续集成 是保证敏捷快速迭代、持续交付的核心环节,也是TBD中保证代码质量和正确性的重要手段。因此基于轻量快捷的提交和持续集成等特性,TBD是一种非常适合在敏捷团队中应用的分支管理模型。

在TBD的日常应用中,研发注重的是代码质量和单元测试(覆盖冒烟用例),不再花大量精力关注提测后变动,如版本管理、发布上线等。测试驱动持续集成 保证TBD以一种良好的正向循环模式运作。

如果测试发现BUG,研发在最新的代码上进行修改,测试也会在最新的代码上进行验证。由于主干分支在大部分情况下是持续可发布的,测试可以根据自己的工作情况随时安排发布上线。

持续集成 CI

对比瀑布模型,敏捷强调测试提前介入到需求分析和技术方案评审中,通过前期的沟通充分了解需求和技术方案。而在TBD的基础上,研发强调代码快速集成、持续部署。通过这样的方式,迫使测试提前介入到对研发任务的了解中,这是一件相辅相成的事。

基于TBD,团队协作变得更简单 Team

如何在实践中更好地应用TBD

对研发:

  • 尽量小的提交代码,高效快速完成code review
  • 每次提交的代码尽量做到向前兼容
  • 重要模块编写完整的单元测试,每次提交保证测试通过
  • 持续集成,持续部署,尽快让最新的代码进入QA等流程接受回归测试
  • 适当结合feature开发,如大特性、无法向前兼容的变更等
  • 给予测试足够的信心,认可持续性地集成测试能覆盖足够的场景

对测试:

  • 熟悉Git,了解常用的分支操作,可以根据需要构建自己的Release分支
  • 关注代码,理解交付的任务和代码间的关系,可以根据需要构建特定功能分支
  • 非必要的情况下,在主干分支完成测试工作,Release分支通常只用于上线前的集成回归或者上线后的热修复验证
  • 给予研发足够的信心,相信研发主观判断和客观结果(单元测试)

结合敏捷,我们可以这样做:

  • 以任务维度形成提交,提交描述应该反应任务内容,任务也可以是代码重构,可以是版本升级等
  • 以故事维度提测,确保主干分支集成的代码是可发布的,提测的形式可以是一个部署包或者一次完整提交
  • 以Tag/Release形成发布,通常只需要通过在主干上选取需要发布的提交命名为Tag。如有必要,可以拉取Release分支,并拣取需要发布的feature提交进行发布(这种情况通常只发生在hotfix或主干分支有很少部分最新提交需要上线,但其余提交还未验证的情况下)
  • 为了使主干分支的提交在迭代需求上符合随时上线的条件,在做迭代planning时,应该尽量保证短周期需求的稳定性,这也是敏捷要求的

总结

无论是敏捷还是TBD,目的都是为了提升开发效率,选择最适合团队的方法才能最大程度地提升效率。 现在我们团队还是以大版本、大项目为基础做计划,偏瀑布式的项目管理和开发模型,这可能更适合部分大客户的定制需求,但不利于快速迭代和交付。从进入公司到现在,最大的感受是开发多线并行,前后端进度不一致,测试疲于应付。虽然我们在使用迭代,但多个迭代并行,占用共同资源,迭代无法如期进行的情况还是存在的。

每个人的精力有限,同时处理多件事情必然使个体的效率下降,导致整体效率下降。 如果想轻装上阵,灵活应变,加速冲刺,不妨试试做好计划,集中资源的迭代方式。

拥抱敏捷与TBD吧!

参考资料

© Cheng all right reserved,powered by GitbookModified At: 2021-12-10 14:52:56

results matching ""

    No results matching ""