这是鼎叔的第一百一十四篇原创文章。行业大牛和刚毕业的小白,都可以进来聊聊。

欢迎关注本专栏和微信公众号《敏捷测试转型》,星标收藏,大量原创思考文章陆续推出。本人新书《无测试组织 - 测试团队的敏捷转型》已出版(机械工业出版社),文末有链接。

持续交付和软件架构的演进是相辅相成的,互相影响,一同发展。

部分观点参考 Eberhard Wolff 的《持续交付实践》一书。

从一开始就引入持续交付

如果我们从项目最开始就引入持续交付,即从技术选型和系统架构设计时就开始考虑持续交付了,就能够一步步完善流水线建设。从一开始就选择更容易自动化的基础设施组件技术,并能控制好程序配置和基础设施搭建的复杂度。让应用程序能够即时优化。

技术选型会影响持续交付的方方面面,比如编程语言会影响编译器的速度,进而影响持续交付流水线的耗时,编程的决策也会影响流水线的交付质量。

反过来,我们从持续交付的需求来调整技术和架构决策,就会使得流水线的设立更简单。

大多数现有项目在设计时并没有考虑持续交付,持续交付是基于快速反馈和精益理论的,价值流映射对于实现快速反馈的理想状态很有帮助,比如,很多代码变更都在等待手工测试,就表明价值流中出现了等待的队列瓶颈,有待我们逐步去消除。

持续交付和技术协同

持续交付可以让技术组织主动使用多元化技术,让开发和运维有协同效应。而传统技术组织的风格则是相反的,即限制技术的种类数量。

因为不同专业岗位的技术团队会在同一个流水线上工作(开发人员,测试人员,运维人员),跨越了组织边界的协作,更容易消除跨团队的不信任感,哪怕部门墙依然存在。

应用程序的可重复部署和可重复验证,带来了更高的质量,也加强了多角色团队之间的彼此信任。

持续交付和软件架构

软件架构包含各个软件组件和它们之间的关系和特征,组件的技术实现是软件架构要呈现的基本决策。一个软件系统非常复杂,只有合理划分出多个组件,开发人员才可以逐一理解和更改它们,组件化互相之间的关系才容易被理解。

组件的划分完全是领域职责驱动的,和具体技术无关,我们需要随着各个功能来调整结构,以支持最终实现的服务目的。通常,我们的开发者在架构定义中容易丢失这个目标,让技术悄然走上前台,而持续交付实践有利于避免这个问题。

组件可以是类、包或者部署单元,它们的技术实现是必要的,但和领域功能拆分的决策无关。每次组件被修改时,整条持续交付流水线都会被运行和测试,最终被验收通过,完整的流水线运行可以暴露必须通过其他依赖组件运行才能呈现的问题。

复杂架构团队总是为接口各版本的联调伤脑筋,我们可以参考伯斯塔尔健壮性法则,让所有组件 “严于律己,宽以待人”,就是组件被调用时能容忍各种错误,调用其他组件时老老实实遵循指南,系统联调的互操作性就能得到保障。

当组件更新期间被其他组件调用,系统处理组件运行中断也应该有容错设计:使用默认值,或者降级服务给一个妥协结果,或者使用断路器避免进一步的调用。这种不传递中断的 “反脆弱” 机制使得整个系统更有弹性。

对于持续交付来说,如果可能的话,组件在内存中不应该具有任何的状态,这种状态应该保存在外部系统如数据库和缓存中。

持续部署如何处理数据库也是一个挑战,如果软件中的数据结构被修改,数据库中的格式也必须被修改,例如添加行或者删除列。

数据库的变更通常涉及大量数据,导致回滚风险大,我们必须找到一个保持数据库稳定的方案,重新部署和修改后的数据库一起工作的组件,数据库本身也可以看作一个组件,也要遵循新旧版本访问的健壮性,等到下一次再更新数据时才彻底删除旧版本的痕迹。

每个组件也有自己的数据库或者数据库模式,数据库变更如果只需要和单个组件协调,就大幅降低了变更风险。

持续交付和微服务

微服务和持续交付更加有广泛的协同作用。微服务就是将系统模块化,从而让每个微服务可以独立部署。众多微服务一起构成了整个系统,而它们各自可以提供一部分用户界面,也可以调用外部系统的服务,把整个系统变成 HTML 链接的组合产品。

微服务架构天然适合持续交付:

流水线可以被划分为多个独立可部署单元,简化创建成本,每次部署只变动一个微服务,风险大幅降低。

微服务之间可以通过适当的接口通信,变更接口时可以分步骤进行:让微服务先同时支持新旧版本,一段时期后,删除旧版本接口。

微服务肯定要有容错设计和弹性,当其他微服务停机时,它仍然能够工作。微服务也有自己的数据库,减少了数据库的更新问题。

因此,微服务不但支持持续交付系统的架构需求,也很容易补充遗留系统,把费时费力的升级工作逐步完成。

由于可部署的工件太多,手动干预的方式太费时费力,所以持续交付对微服务架构也是至关重要的。

持续交付和特性团队(feature team)

微服务和持续交付,更适合敏捷团队,支持个体责任制和自组织。

微服务允许技术上的自由,甚至不限制平台和编程语言,它帮助团队降低和其他特性团队的协调成本,而单独的持续交付流水线还可以让特性团队完全独立地把软件发布到生产环境,让团队获益。

真正的特性团队能让大型产品能以特性为单位进行 “实验”,能度量和管控特性级别的成功。持续交付能帮助实验更快完成,通过单特性发布得到结果,甚至实现 “精益创业” - 客户没有付费的功能就是浪费。

在大型敏捷团队的主干持续交付过程中,特性开关就有非常好的优点,通过一个开关激活或者关闭某个特性,让用户在特定期限内用上某个特性,风险也较低。

测试团队需要测试特性开关的运转是否符合预期,需要采取措施将测试和生产运营分离开。同时团队可以测试客户对新特性的喜好程度。

特性开关也有一些缺点,它增加了软件的复杂度,尤其是特性开关的不同组合和不同测试环境,都给测试人员带来不小成本。

持续交付和环境

环境问题始终是持续交付发挥价值的拦路虎。持续交付的环境完全相同时,就可以消除软件外部的错误来源。

但是在环境治理上,IT 部门和业务研发部门的态度可能不同。IT 部门更专注统一稳定的环境建设,业务部门更关心易用性和灵活性。

持续交付的环境希望有 “状态” 的概念,每个当前状态都可以被追溯,治理中发现的规律会给团队带来可靠性。

测试环境的管理职责应该放在哪个团队?鼎叔认为这要看治理范围。如果是环境的快速搭建、可用性验证、纪律、可用性度量,测试团队可以承担管理职责,但是底层体验问题可以让开发运维团队先进行专项改进,比如自动化配置和依赖部署,资源自动创建,监控和优化等。

最终,持续交付看板上应该有测试环境可用性的实时度量指标,随时掌握环境。

持续交付的日志系统

日志系统对于运维和开发非常重要,日志看起来是非常简单的记录应用程序信息的方法,实则有不少特点:

写入很简单,各种外部技术都可以实现,只需要” 添加 “就可以把信息纳入日志。无需付出很大的工作量就可以持续保存。

日志文件的覆盖和拆分,分析和检索也很容易,我们可以很容易地解读日志信息。日志文件可以和具体的分析技术或监控技术无关。

正因为日志是需要人来处理的,它就应该尽可能容易理解,否则在深夜遇到线上问题,责任人是没有充分的时间和精力来分析复杂的信息关系的。

因为日志有海量的记录容量,被写入的信息重要程度是大相径庭的,日志系统会为信息提供不同的保存级别,由此过滤掉大多数不重要的信息,最小化生产系统的数据量和性能影响。比如必须记录 Error 级别的信息,放弃部分 Info 级别的信息,并针对特定的错误把 Debug 级别的信息写入日志。

为了生产数据的安全性,日志信中的敏感信息不能简单地发送给开发人员,可以利用脱敏或者散列化工具,让开发人员不能判断具体的用户,但是知道这个日志对应于同一个人。


↙↙↙阅读原文可查看相关链接,并与作者交流