关于git:特性分支-VS-特性开关哪个是最合适的工具

114次阅读

共计 4905 个字符,预计需要花费 13 分钟才能阅读完成。

起源:DevOps.com

作者:Pete Hodgson

译者:小江

英文原文链接:https://devops.com/feature-branching-vs-feature-flags-whats-right-tool-job/

软件开发团队的代码分支管理策略会对其公布高质量软件的速度产生重大影响,这篇文章咱们将探讨在同一代码库中实现多个并行开发工作流的几种不同办法的利弊。咱们将看到两个次要的因素:合并代码抵触的老本以及独立公布性能的能力通常是无奈兼得的,但个性开关为咱们提供了一种解决这种矛盾思路。

一、代码合并抵触问题

新产品开始时代码库还比拟小,通常只有少数几个开发人员在开发,这种状况下不须要太多的正式开发流程标准。然而,即便一个团队只有两个开发人员,在同一时间解决雷同的文件时仍须要尽量避免合并抵触。

只管大家致力防止工作内容相互影响,但看起来息息相关的工作分支,常常还是会批改到同一个文件。有时,正是这些意外的合并抵触会造成微小的苦楚 — 任何一个资深的 iOS 开发者想必都经验过合并第三方 XIB 文件的抵触问题。在这篇文章中,咱们将探讨一些不同的办法来解决多个开发人员在同一代码库中工作时造成合并抵触的挑战。

有些人可能会说,当初的合并抵触并不是什么大问题,应用古代的版本管理工具,例如 Git,根本都能解决,这是一种现实状态。古代版本管理工具的确让创立分支变得非常简略,但并不总是能使合并这些分支内的并行开发代码变得简略。Git 有一些弱小的性能,在可能的状况下主动合并代码,但 Git 不能解决所有合并问题。如果并行批改影响到了大型的 XML 文件、或 XIB、IDE 工程文件,Git 是无奈自动化解决这些合并抵触问题。

最重要的是,Git 无奈主动解决代码语义抵触。例如,在一个分支中,Alice 重新命名了一个办法,而在另一个分支中,Bob 减少了该办法的一个新调用。当这两个分支合并时,Git 就无奈辨认出 Bob 的分支正在调用一个应用旧名称的办法, 而 Bob 的代码正在调用一个曾经不存在的办法。事实上,Git 不会给 Alice 或 Bob 任何提醒,因为这些语义抵触是咱们目前的工具无奈检测的。

咱们只有在尝试编译合并后的代码库时才会发现语义抵触,而且这只是其中的一个问题。如果代码是动静类型的语言,例如 javascript,那么咱们可能直到用户开始报告线上的应用程序解体时才会被发现。

当变更的老本越来越高时,在零碎中进行一些小优化投入产出比就会升高。这引入了一个奥妙的阻力,随着工夫的推移,对代码库的外部品质不利。更重要的是,可能逐步改善代码库或阻止其逐步进化的那种小而宽泛的重构,正是会常常导致合并抵触的那种变更。在我看来,这是基于分支开发的真正隐性老本 –它克制了那种 “ 童子军军规 “ 的改良,而这种改良能够避免代码库的某些区域逐步进化为禁区。(童子军军规:永远把露营地弄得比你达到时还要洁净,指随时解决和优化手中的问题)

因而,在介绍了合并抵触会引起的问题后,上面让咱们看看如何防止合并抵触。

二、在骨干上同步批改代码

一个刚开始开发新利用的小团队,最后可能会试图通过让所有开发人员频繁地推送变更到共享的骨干分支来升高产生大的意外合并抵触的危险,这是继续集成的外围准则之一。当每个人都在共享的骨干分支中频繁地同步他们的批改时,意外的合并抵触能够在晚期时裸露进去并解决掉。

可怜的是,让多个工作落在一个共享的骨干分支上,会有一个很大的问题。如果任何一个工作没有筹备好公布,那么共享分支上的任何货色都不能被公布。让咱们用一个假想的例子来看看为什么。

Alice 和 Bob 是挪动应用程序的两个开发人员,他们有两个正在进行的工作。Bob 正在对用户偏好的工作形式进行大修,而 Alice 正在实现一个要害的新性能,大老板规定必须在本周末前将其推送到利用商店。这个团队通过频繁地在骨干提交代码来避免出现大的合并抵触。

到了周四,Alice 正在完结她的工作同时也开始做功能测试。在对应用程序进行个别的测试时,她留神到用户偏好模块存在闪退景象,便问 Bob 是否晓得是什么起因导致的。Bob 解释说,他正对这个模块进行重构,重构工夫可能会比预期工夫长一些,在实现前可能会存在 bug。但 Alice 的新性能本周又必须上线。通过了两天漫长的工夫,Bob 和 Alice 终于一起回滚了 Bob 的更改,因为其中一些更改曾经与 Alice 的新性能的批改纠缠在一起了。最终他们赶上了周六在产品商店上架,防止了一场危机。

下面的例子能够看到,因为 Alice 和 Bob 在一个共享分支上提交代码,他们本来互相独立的开发工作相互耦合在了一起。Alice 无奈漠视 Bob 的工作而独立公布本人的变更,Bob 也是如此。这是在共享分支上工作的一个大问题,好在前面咱们会介绍一些办法能够缓解这种状况。

三、个性分支

为了防止这种工作耦合的问题,开发团队往往会放弃将正在编写的代码推送到共享分支上的形式。有些团队会抉择在本地机器 master 分支上工作,在工作实现后再推送到团队的共享仓库。其余团队会抉择应用个性分支,在独立的分支上进行独立的工作,只有在开发实现后才合入到骨干。

顺便提一下,当应用像 Git 这样的分布式源码控制系统时,这两种办法实质上是等同的;惟一的区别是,未合并的开发中的代码是在近程个性分支中可见,还是暗藏在开发者的本地骨干上。因而,我把这两种形式都称为个性分支。

那么,如果一个团队应用了个性分支,那么他们所有的问题都解决了,对吗?惋惜不是,咱们从新引入了合并危险。个性分支上进行的工作,在被合并到共享的骨干分支之前,并没有与其余的批改集成。每当两个工作同时批改到雷同的文件时,无论是无心还是无意,都会存在一个潜在的合并抵触,这个潜在抵触会持续扩充,直到其中一个工作的分支合入主干。有些团队会通过频繁地将骨干分支的批改合并到个性分支中来缓解这一问题。

然而,当存在并行的开发分支时,这种策略是没有成果的。例如只有当 Bob 的分支合并到骨干上之后,Alice 的分支能力合入他的批改。这两个并行分支的潜在抵触只能等到 Alice 下一次合入主干代码的时候去解决了。

有些团队还会尝试 “穿插合并” 来解决代码合并抵触的问题,将一个个性分支的代码合并到另一个个性分支代码上,来缩小分支之间潜在的合并抵触。然而一旦你将两个个性分支合并后,事实上你还是创立了一个含有进行中工作的共享分支,这和两个团队将进行中的工作合入共享 master 分支是一样的:两个工作的代码变更内容依然纠缠在了一起,所有的性能都是耦合在一起的,无奈独立公布。

总的来说,个性分支容许团队对工作进行解耦,让局部性能能够独立公布。然而,当个性分支做了大量的批改时,它们会带来大量合并抵触的危险。只有在其余并行工作曾经实现并合入的状况下,从骨干分支拉取代码合入本人的个性分支才会有帮忙,而分支之间的穿插合并与在共享骨干分支一样,都会将多个个性耦合在一起。

四、个性开关

如果一个团队想防止个性分支带来的合并抵触危险,他们有什么抉择呢?他们能够回到在骨干上频繁集成变更的形式,但咱们说过这样做的一个次要问题是以前互相独立的开发工作当初被耦合在一起,不能独立公布。

这时,一种叫做个性开关(又称个性标识、比特或翻转器)的技术就能够帮上忙了 个性开关通过将进行中的代码置于一个 “标记”或“开关” 之后来隔离他们的影响。工作中的代码只有在标记被关上时才会被执行。否则,它将作为 “埋伏代码” 存在于代码库中。上面是一个根本个性开关的应用办法:

if(featureFlags.isOn(“my-new-feature”) ){showNewFeatureInUI();  
}

除非  my-new-feature 开关被配置为 “on”,否则新性能将不会在应用程序的用户界面中展示进去。 这意味着,即便实现新性能的代码齐全是谬误的,只有该性能的标记是敞开的,应用程序也能够失常公布。通过应用个性开关,能够将正在进行中的代码推送到共享分支,而不障碍该分支的公布。如果 Bob 的性能曾经实现了一半,而 Alice 想公布她的性能,团队能够创立一个公布版本,把 Alice 实现的性能关上,而把 Bob 未实现的性能敞开。咱们既失去了将开发工作继续集成的益处(缩小了合并抵触的危险),又确保这些工作的公布是解耦的。

这种技术并不是什么新技术。它是 trunk based 的开发技术中的一部分(你能够晓得这个技术不是新的,因为这个名字应用了 trunk 而不是 mastermoniker,后者在明天因为 git 的主导地位而更加广泛)。Flickr、Etsy、Github 和 Facebook 是这种技术的一些比拟出名的支持者。正是个性开关的应用,使得 Facebook 能够做到 feacebook.com 网站基于骨干每天公布两次。

五、个性开关的毛病

与到目前为止探讨的其余办法一样,个性开关也有其毛病。它们在代码库中引入了相当多的乐音,因为咱们当初须要为任何开发中的个性显式的实现一个分支逻辑。这种乐音随着工夫的推移会产生一些代码异味,除非时刻注意将不再须要的个性开关移除。测试人员可能须要一段时间来适应带个性开关的应用程序——将未实现的、未经测试的代码公布到利用商店的想法须要工夫去承受。如果开关能够在运行时近程管制,那么团队须要明确,新的开关配置状态必须通过测试能力在用户的应用程序上失效。

最初,某些类型的改变难以通过个性开关来爱护——例如波及大量文件变动的小改变就是一个挑战。令人欣慰的是,应用个性开关并不是一个非黑即白的计划;个性分支依然能够用来解决那些不适于应用个性开关的繁琐变更。

六、正当应用个性开关

当一个团队开始采纳个性开关时,通常会遇到下面提到的一些挑战,并最终找出解决问题的办法。上面是一些在代码库中胜利应用个性开关的技巧。

1、开关要有过期工夫

很多团队在刚开始应用这种办法时,都会有些急功近利。他们偏向于引入大量的开关,却不想花工夫去革除那些不再须要管制的开关。请确保花工夫清理过期的开关 – 它们连累你的代码设计并带来困惑。一些团队采取了相当踊跃的办法来确保旧开关失去清理,比方在创立开关时设置 “ 定时炸弹 ”,或者在肯定工夫后仍在应用时抛出一个异样。其余技术包含在创立开关时就在团队工作列表中增加一个对应的革除工作。

2、开关不是『银弹』

在一个新的工作中并不总是能够应用个性开关。个性开关更适宜于新性能或者代替性能的开发,在这些性能的入口能够在代码中独自的地位进行管制,通常通过可暗藏的按钮或者通过 UI 界面操作触发。而另一些工作,例如重构,则很难通过一个开关来包裹。对于这种状况,须要思考应用个性分支,现实状况下最好拆解为能够增量开发的一系列子工作分支而不要应用一个长期的分支,以缩小大量合并代码带来的抵触问题。

七、总结

个性开关和个性分支都是解耦并行代码变更的办法,容许团队在公布变更时缩小协调开销。个性分支很容易上手,但会导致苦楚的合并抵触。这种对抵触的恐怖往往会克制对代码库进行增量改良的行为,并可能导致代码库的某些区域最终成为 “ 禁区 ”。个性开关容许团队实际真正的继续集成,并将代码变更与个性公布齐全脱钩,但也必须付出实现每个开关的老本作为代价。

个性开关不是银弹也不总是正确的抉择,但对于研发团队上手很简略,你能够从一个简略的 if/else 语句开始,去摸索个性开关带来的价值。

对于作者

Pete Hodgson 是 Rollout.io 的征询参谋,同时也是一名软件工程师和架构师。次要是专一于通过测试自动化、个性开关、基于骨干的开发和 DevOps 等实际以可继续的速度继续交付软件,他的客户包含旧金山初创公司到财产 50 强的企业,同时也常常负责播客小组成员,是美国和欧洲的定期会议发言人,也是一名特约作者。

FeatureProbe 是一个高效的个性开关  (Feature Flags)  治理服务,它提供了灰度放量、AB 试验、实时配置变更等针对性能粒度的一系列治理能力。目前 FeatureProbe 应用 Apache 2.0 License 协定曾经齐全开源, 开源地址:https://github.com/FeatureProbe/FeatureProbe

正文完
 0