当所有开发都在分支机构上时,如何重构?


24

在我公司,我们所有的开发(错误修复和新功能)都在单独的分支机构进行。完成后,我们将其发送给质量检查人员(QA),由该人员在该分支机构对其进行测试,当他们给我们开绿灯时,我们会将其合并到我们的主分支机构中。这可能需要一天到一年的时间。

如果我们尝试压缩分支上的任何重构,我们将不知道它会“退出”多长时间,因此在合并回它时会引起许多冲突。

例如,假设我要重命名一个函数,因为我正在使用的功能正在大量使用此功能,而我发现它的名称确实不符合其用途(再次,这只是一个示例)。因此,我四处寻找该函数的每种用法,并将它们全部重命名为新名称,并且一切正常,因此将其发送给质量检查人员。

同时,正在进行新的开发,并且我的重命名函数在main分支的任何分支上都不存在。当我的问题重新合并后,它们都会崩溃。

有什么办法解决吗?

并不是说管理部门会批准仅重构的问题,因此必须将其与其他工作联系在一起。它不能直接在main上进行开发,因为所有更改都必须经过质量检查,而且没人愿意成为打破main的混蛋,以便他可以执行一些不必要的重构。


您正在使用什么版本控制?DVCS和集中式服务器模型有不同的方法。此外,正在剥离哪些发展分支?如果接受功能分支,其他开发分支如何接管更改?

2
顺便说一句,当前分支结构图可能确实有帮助。重构困难的问题根源很可能部分是由某些非常规分支策略引起的(有关此类示例,请参阅programs.stackexchange.com/questions/210360)。我还建议阅读vance.com/steve/perforce/Branching_Strategies.html以获得一些想法和背景(如果我能够回答这个问题,这将是一个主要参考点)。

1
最后一段进行了总结-如果业务部门没有意识到其价值,则无法进行重大重构。您需要与测试团队合作来解决他们的时间表。(我怀疑您的QA确实是拖延测试(他们戴上了假发和口红,并假装自己不是这种东西。)真正的QA团队会告诉您要重构的内容,而不是妨碍您。)
mattnz

1
@mattnz:你说得对。他们不是真正的质量检查小组。他们主要是客户支持。我认为他们的许多责任应该转给开发团队,因为他们根本无法处理我们向他们倾销的一切,但这是管理问题,也是我尚未赢得的战斗。
mpen

3
你想念我的事了。测试!=质量检查。质量检查负责质量监控,旨在改善业务成果。测试试图通过发现缺陷来证明它们不存在。
mattnz 2013年

Answers:


12

在此环境中,有几个问题混合在一起使重构具有挑战性。与此混杂的是一些非技术性的问题(“但这是管理问题,我还没有赢得一场战斗”)。

要研究的第一个问题是长期运行的分支。这些分支很难跟踪开发人员视野之外的更改。要解决此问题:

  • 代码完成后-进行一次编码(如果需要,让客户支持人员查看),但是将其快速合并到开发中,以便依赖于它的其他更改将能够被采用,并尽早发现冲突的更改进行中。
  • 如果出于某种原因分支在重构过程中确实运行了很长时间,那么将其从稳定合并到分支中以接管更改和重构是一种好习惯。通常,这样可以最大程度地减少从要素分支合并到稳定分支的冲突和意外情况。
  • 全面的集成测试需要针对发布而不是功能进行。在这种环境下,功能可能会或可能不会与系统完全集成。尽管可以单独对功能进行完整性检查,但它无法确定发行时的问题。
  • 从代码完成到合并的整个过程(称为开发-从主/稳定/发布分支​​有其自身的问题,即没有掌握最新的开发更改),它应该不会太长。您等待的时间越长,丢失的知识就越多,并且代码很难与其他代码行集成在一起。

与此相关的另一个问题是,我提到以上几点是分支随着时间的变化而变化。它开始时是开发人员在其中进行开发的开发分支,然后成为测试区域(在此进行的测试在整个应用程序中可能有意义吗?),然后合并为稳定的(大概已发布)。再次测试?)。

使用较短的开始到结束时间,其他分支可以更轻松地进行重构。

鼓励开发人员获得整个环境。挑剔的变化可能会导致...可以说是有趣的开发人员环境。尽管选择樱桃有其用途,但将其作为将更改拉入分支的默认模式可能令人担忧。

重构是理想情况下不断进行的工作,如果不是经常停工的话,则经常进行重构。分支,做一个简单的重构,运行单元测试以验证一切仍然正常(它的单元测试了,对吗),然后合并回到稳定状态。将信息传递给其他开发人员,以将您重构的那些更改拉到他们自己的分支中。

对于开发人员来说,拥有代码质量很重要。虽然功能的方向来自外部,并且时间分配通常不是我们自己的,但代码质量是值得引以自豪并为此付出时间的。

您可能会发现以下问题对于分配时间来处理技术债务很有用:

您可能还希望看一下声纳之类的工具,这些工具可以帮助确定代码重构最需要工作的区域。该技术债务插件的东西,可以在代码库来帮助一点摆脱债务随着时间的累积。

通常需要指出,用于处理技术债务的投资回报是开发团队的功能和错误修复的更快处理时间。


测试基本上在三个时间点进行。一次是声称已解决问题(以确保满足所有要求且没有大问题),一次是在将其合并回默认值(集成测试)时,又在我们进行构建时(集成了所有挑选的樱桃)问题/最终查看)。我认为在我们的环境中挑选樱桃是必要的,因为我们与非常特定的客户一起运营SaaS。我会看一下这些链接,谢谢您的指点!编辑:实际上,在生产中还有另外一个查找,以确保其正常运行。
mpen

3

通常,我正在与当前版本“并行”开发重构版本,即在同一代码库中,但未从核心应用程序引用它。当新的解决方案完成并经过测试后,我将开始实际的重构。

示例1.假设我有Thing,让它成为函数,接口,模块等。我想重构它。我正在同一代码库中创建Thing2,它是Thing的重构版本。完成并测试后,我将重构所有引用Thing的内容,以Thing2替换它。通常,此步骤花费的时间相对较少。

如果实际的重构花费了太多时间来保持同步而又不花很多钱,那么我将采用所有相关的功能,并同时进行并行重构。

示例2.我有一个新的渲染后端,它是旧版本的重构版本。但是它与旧的渲染前端不兼容。因此,我需要重构前端。再说一次:在相同的代码库中。完成所有操作后,我只是在更改前端实例的类,理想情况下,只需进行一小段提交即可。

是的,可以递归得出结论,所有步骤必须并行进行。但这通常在代码库中耦合过多或更改速度过快时发生。

最后,当新代码集成并运行良好时,可以从代码库中删除旧功能,并可以重命名新功能以获得旧名称。

通常,想法是并行准备新功能,并且只需一步就可以切换到使用这些功能。

约翰·卡马克(John Carmack)使用了这种(或至少类似的)方法,也许他的博客文章对此进行了更好的解释:(链接)


这是一个好方法。我试图记住是什么真正促使了这个问题……我认为这不是非常适合并行化的东西。或者如果是这样,我认为我担心的是这种方法会在代码库中造成很多碎片。我们有做事的“旧方法”和“新方法”,并且旧事物正在以冰冷的速度被替换,但它却使开发人员感到头疼,因为现在他们基本上必须了解两个(或更多)系统。
mpen

1

当实际上是在需求方面时,在技术方面看起来似乎很困难。

真正的困难在于开发针对不同分支的不同需求。团队的经理和架构师应制定决策,以使不同的业务需求可以共存。

在用所有开发人员的相关输入做出正确的决定后,完成ZBB流程和Co-Dev时会“妥协”,而后言可以使您实现所需的实现而不必考虑-我将如何合并我的代码。

ZBB代表基于零的预算。说到Co-Dev,我的意思是很少有人在并行编程中工作。


2
什么是“ ZBB”和“ Co-Dev”?
蚊蚋

ZBB - en.wikipedia.org/wiki/Zero-based_budgeting。说到Co-Dev,我的意思是很少有人在并行编程中工作。
Yosi Dahari

1

在我看来,问题是您在分支机构上的工作时间过长。冲突的成本随着每个人停留在分支上的时间而成倍增长,因此,如果冲突时间很长,则几乎没有进行任何重构的机会。


0

您的问题是您使用的分支模型。您可以在分支上进行开发,完成并准备进行质量检查时,该分支将合并到“中间主干”(有时称为“集成”或“测试”)中。开发下一个功能时,您可以从中间中继分支。

通过此模型,您可以在不同分支上并行开发多个功能,将它们全部合并到Integration分支上以发送给QA,并且还维护一个发行版主干(您在验证它们时将收到的代码库QA合并到主干中) )

您假设传送给QA的更改将在不进行重大修改的情况下通过-如果QA代码返回了删除一半更改的说明,则必须还原,但如果不这样做,它将使您的开发更加顺畅。因此,您基本上是将新功能的分支转移到您的主线代码(即,合并传递给QA的代码后的主干)上,而不是现在的主干代码(即当前主干)上,因此不再根据先前版本的代码库进行开发。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.