当功能标志有意义和没有意义时(2019年)

2020-09-22 10:31:07

在过去的几年里,我在多个团队工作过,当涉及到功能标志时,他们采用了非常不同的策略。我看到了两者的优缺点,随着时间的推移,我发现自己不同意任何关于使用它们的原教旨主义立场。这个主题有很多细微差别,我认为值得更仔细地考虑功能标志有意义和没有意义的各种场景。

在几个主要场景中,功能标志很有意义。第一个是当它用于A/B测试时,基于他们随机分配的处理,您绝对希望不同的用户有不同的行为。我看到这一策略在亚马逊应用得非常好,新功能由一个“功能标志”控制,而“功能标志”实际上是由内部A/B测试框架控制的。该框架随机让一些亚马逊客户接触到这一新功能,然后监控他们随后的行为,以评估推出该功能的业务影响。

起初我对此持怀疑态度,但很快就被该框架的易用性以及它提供的关于某些功能的优点(或缺点)的宝贵见解所打动。“本月风味”的决定被真实的数据所取代。如果不使用“特征标志”来动态切换新特征,所有这些都是不可能的。

功能标志的另一个很好的用例是,当您在处理一个非常复杂的史诗时,需要在系统的不同部分完成许多不同的子任务。数量太多、侵入性太强的子任务,无法在单个拉取请求中完成。

在这种情况下,试图将所有这些完全不同的更改保留在辅助分支中,并协调同步合并和部署,将会导致灾难。更易于管理的方法是在主标志后面控制任何破坏性更改,以增量方式合并和部署所有子提交,并在所有部分就位后执行标志翻转。

功能标志的最后一个使用情形是您无法控制您的部署。例如,以Facebook Android应用程序为例,它包含由数百个不同团队贡献的代码,所有这些代码组合在一起并部署为单一的二进制代码。在这种情况下,执行回滚可能是不可行的。出于实际的、政治的、官僚的甚至是营销的原因。在这种情况下,功能标志允许您的团队切换新功能或减少风险更改,而不必回滚或部署任何新的二进制文件。

以上都是功能标志的奇妙用例,但我也看到团队受困于过度使用它们的策略。例如,强制要求每一次代码更改都应该在一个功能标志后面,“以防我们犯了错误”。

风险管理确实应该是所有团队的优先事项。但是,有比依赖功能标志更好的方法来实现这一点,特别是当您的团队能够控制自己的部署时。您的自动化测试套件和/或QA流程应该可以捕获绝大多数错误。最后几个落后者应该使用增量部署、生产警报和回滚来处理。

此外,一旦检测到任何问题,像Google这样的地方的建议是先回滚,然后再调查问题:

我们在谷歌已经看到过很多次了,匆忙部署的前滚修复要么不能解决原始问题,要么确实让事情变得更糟。即使它修复了问题,也可能会发现系统中的其他潜在错误;您正在将自己从已知良好的状态进一步带到一个没有经过定期严格的QA测试的版本的荒野中。在谷歌,我们的理念是“回滚是正常的”。当在新版本中发现错误或合理怀疑错误时,发布团队首先回滚,然后再调查问题。

当事情着火时,您最不想做的就是找出bug的根本原因,并找出哪个翻转标志可以安全地解决问题。这甚至可能解决不了问题--不能保证即使您的队友试图将他的更改放在特性标志后面,他也不会无意中引入一个无法通过翻转标志解决的错误。

特性标志是二进制回滚的替代方案,它们绝对不能替代强大的自动化测试套件和健壮的QA流程。如果您依赖功能标志来修复生产错误,那么您应该停止并评估您团队的实践。风险厌恶通常是你的团队进入厄运循环的味道,随着时间的推移,这种循环只会变得越来越糟。

在这一点上,您可能会感到疑惑,为什么我们无论如何都不应该使用功能标志。毕竟,“纵深防御”…。而且,拥有更多细粒度的灵活性也不会有什么坏处,对吧?

虽然功能标志在某些情况下很好,但我们也应该记住它们的成本。软件工程主要是管理复杂性的练习。而且每个特性标志都会立即使程序员必须理解的角例数量增加一倍,并且需要处理您的代码。但是,如果启用foo,禁用Bar,并且我们在同一天对BAZ和KAZ进行独立的A/B测试,会发生什么情况?根据我的经验,复杂性的这种组合爆炸可能并将导致错误。更不用说放慢你的团队做出任何改变的速度了。

“但这些功能标志只是暂时的。你应该尽快把它们移走!“。

当然,我们也不应该让我们的科技债务积累起来,我们应该虔诚地遵循每一项最佳实践。不幸的是,这在任何企业环境中都不会发生。即使是在伟大的团队中,面对新的请求,科技债务也经常被排在次要地位。团队的新人或即将离开团队的人,在成功推出后,并不总是有足够的纪律来清理他们的旗帜。有时,这些任务只是从缝隙中溜走,被遗忘了。

没有什么比KCG的崩溃更能说明这一点了,当时一家金融公司在30分钟内损失了5亿美元,几乎破产,部分原因是功能旗帜后面的死代码。

失败的原因是多方面的。然而,其中最重要的一点是,以前用于启用Power Peg…的标志。Power Peg从2003年就已经过时了,但大约8年后仍然保留在代码库中。

2005年,对Power Peg代码进行了修改,无意中禁用了本可以防止这种情况的安全检查。但是,此更新当时被部署到生产系统,尽管没有进行任何努力来验证Power Peg功能是否仍然有效。

功能标志是一个强大的工具,可以帮助您试验新功能、管理复杂EPIC的推出,并缓解与不控制团队部署相关的问题。

但它们是要付出巨大代价的,表现为代码复杂性、技术债务、开发速度较慢,以及不可避免的错误。

尽管这可能很诱人,但这里没有灵丹妙药。权衡利弊,在有意义的时候明智地使用这个工具。