“功能分支”是指每个功能在其自己的分支中开发,并且只有在经过测试并准备发货后才合并到主线中。这样,产品所有者可以选择进入特定货件的功能,以及在更重要的工作进入时(例如客户打电话给MD进行投诉)部分写入的“停放”功能。
“重构”正在转变代码以改进其设计,从而降低变更成本。如果不继续这样做,你往往会得到更难以编写测试的代码库。
在现实生活中,始终有已售出新功能的客户以及由于政治所有客户必须看到“他们的”群体正在取得进展的功能。因此很少有时间没有很多半成品功能坐在树枝上。
如果已经进行了任何重构,那么“功能分支”中的合并将变得更加困难,如果不是不可能的话。
我们是否只能放弃能够进行任何重构?
另请参阅“How do you handle the tension between refactoring and the need for merging?”
答案 0 :(得分:12)
功能分支肯定会使重构变得更加困难。它们还使得持续集成和部署更加困难,因为您需要构建经过测试的并行开发流的数量不断膨胀。您也正在消除“持续集成”的核心原则 - 每个人都在使用相同的代码库,并“不断”将他们的更改与团队的其他变更集成在一起。通常,在使用功能分支时,功能分支不会持续构建或测试,因此“功能分支”代码首次通过生产构建/测试/部署过程运行时,它是“完成”并合并进入行李箱。这可能会在开发过程的后期和关键阶段引入一系列问题。
我持有有争议的观点,即你应该以(几乎)所有费用来避免功能分支。合并的成本非常高,而且(或许更重要的是)未能“不断集成”到共享代码库中的机会成本更高。
在您的方案中,您确定每个客户端的功能都需要单独的功能分支吗?您是否可以在后备箱中开发这些功能但是在它们准备好之前将它们禁用?一般来说,我认为以这种方式开发“功能”更好 - 即使它们不是生产就绪,也要检查它们,但是在它们准备就绪之前将它们从应用程序中删除。这种做法还鼓励您将您的组件保持良好的分解并屏蔽设计良好的接口。 “功能分支”方法为您提供了在代码库中进行全面更改以实现新功能的借口。
答案 1 :(得分:10)
我喜欢这个引人深思的论文('放弃重构'),因为它丰富了讨论:)
我同意在拥有大量并行代码时必须非常小心更大的重构,因为冲突可能会大大增加集成工作,甚至会导致在合并期间引入回归错误。
由于重构与功能分支问题,因此存在许多权衡因素。因此,我根据具体情况决定:
总结一下,我会根据代码行计划我的重构:
答案 2 :(得分:5)
重构和合并是Plastic SCM关注的两个组合主题。实际上,有两个重要的领域需要关注:一个是(在合并期间)处理已经moved or renamed on a branch的文件。这里的好消息是,所有“新时代”的SCM都会让你正确地做到这一点(Plastic,Git,Hg),而旧的SCM只会失败(SVN,Perforce甚至更老的)。
另一部分是在同一个文件中处理重构代码:你知道,你移动代码而其他开发人员并行修改它。这是一个更难的问题,但我们也会使用新的merge / diff工具集关注它。找到xdiff info here和xmerge(交叉合并)here。关于如何find moved code here(与“超越比较”相比)的良好讨论。
虽然“目录合并”或结构合并问题是核心问题(无论系统是否成功),但第二个问题更多的是工具问题(你的三向合并和差异工具有多好)。您可以免费使用Git和Hg来解决第一个问题(甚至Plastic SCM现在也是免费的)。
答案 3 :(得分:1)
部分问题在于,大多数合并工具都太愚蠢,无法理解任何重构。方法的简单重命名应该合并为方法的重命名,而不是作为101行代码的编辑。因此,例如,在其他分支中对方法的附加调用应该自动处理。
现在有一些更好的合并工具(例如SemanticMerge)基于语言解析,旨在处理已移动和修改的代码。 JetBrains(ReShaper的创建)刚刚发布了blog。
这些年来有很多research,最后有些产品进入市场。