大规模重构战略

时间:2008-12-01 07:26:11

标签: refactoring legacy

我目前正在使用一段代码,其中逻辑和数据访问都存在于GUI类中。显然,我想改善这种情况。

目前的结构基本上是:

  • 大泥球

最终目标是实现类似DDD的结构:

  • DAL
  • 域名模型
  • 服务层
  • 演示模型
  • GUI

那么,你会如何解决这个问题?

9 个答案:

答案 0 :(得分:15)

永远不要尝试“大爆炸”。它几乎总是吹在你的脸上,因为当其他一切都失败时,这是一个高风险,绝望的措施。

分而治之:这很有效......如果你的世界只有两面。在真正的软件中,你必须同时征服这么多阵线,你很少能够生活在黑白幻想中。

我想在我职业生涯的大部分时间里,我一直在使用类似“扼杀”的东西:逐渐将糟糕的旧代码变成闪亮的新代码。这是我的食谱:

从某处开始,在哪里并不重要。编写一些单元测试,看看代码的真实行为。找出它做你认为它做什么的频率和不经常做的频率。使用您的IDE重构代码,以便进行测试。

在第一天之后,猜猜你是否已经开始在正确的地方将这个怪物分开。如果是这样,继续。如果没有,找一个新的地方重新开始。

这种策略的优点:它只需很小的步骤,因此可以控制风险,如果出现问题,如果必须在上周你一直在处理的代码中。

缺点:需要花费大量时间而且你会感到沮丧,因为通常情况下,进展只会看起来如此缓慢,直到“结”突然爆发,突然之间,一切都开始就像魔法一样落到了位置。

答案 1 :(得分:6)

我从来没有听说过“扼杀者申请”这个词 - 我喜欢它。在可能的情况下,这总是一个很好的方法,它确实可以最大限度地降低风险并且非常务实,一点一点地削减大型建筑。

如果根据我的经验不起作用,那么需要立即进行合理重大的更改 - 需要进行一些重构(或大量黑客攻击)的更改。在那种情况下,我经常发现我需要做的改变是在泥球大的核心,没有选择,但变脏 - 即使应该是标准维护或轻微的增强变化只是可怕的和主要的重构是最好的选择。

对于那些情况,我会分而治之 - 我一直瞄准的第一个目标是可测试性,一旦你完成所有其他事情就更容易了。实际上,这通常是我从重大泥浆中重构的主要驱动因素之一 - 这种代码通常几乎无法测试,希望有一些示例UI输入和输出,但有时甚至会丢失

因此,当面对将所有内容集中到UI中的代码时,我通常首先将离散的功能单元分解为类和方法,然后将这些代码部分推送到域或服务层。一点一点地做到这一点大大降低了破坏某些东西的可能性,并且当事情出错时更容易确定破解代码的位置。

运行在每次更改结束时可用的任何测试用例,并确保您仍然遇到某种基线。

如果你去编写好的单元测试,你可以开始减少问题的规模,我发现采用扼杀者方法很快变得切实可行 - 通过适当的单元测试或至少是正确的框架来允许编写体面的单元测试,逐渐替换部分功能变得更加实用。

答案 2 :(得分:4)

我偶然发现了“天皇方法”,似乎很有希望攻击这种性质的问题。

http://mikadomethod.wordpress.com/

还有一篇关于2010年Øredev的Mikado方法的讨论。

http://oredev.org/2010/sessions/large-scale-refactorings-using-the-mikado-method

答案 3 :(得分:2)

Big bang / Big重新设计/重写SW ......或者其他任何名字都不适用于生活SW。 原因是:

  • 您仍然需要(可能)使用相同的资源来支持现有的SW。

  • 您可能没有重写的要求。您的旧代码具有嵌入其中的所有要求。您的工程师都不了解所有SW域和所有要求。

  • 重写需要时间。在这段时间结束时,您会发现现有的SW已更改为支持在此期间所需的内容。 你的新SW实际上是从原版拆分而且需要合并(这也需要时间)。

答案 4 :(得分:1)

取决于你是否必须始终处于工作状态,以便你可以在任何时候进行错误修复和部署,然后Devide和Conquer将是一个很好的解决方案。如果您可以维护旧代码,在处理新代码时(并且让跟踪器将错误修复应用于两个代码库),重写可能是更好的解决方案。

答案 5 :(得分:1)

如果通过重构,您的意思是在不修改功能的情况下改进代码,我首先要创建一个自动回归测试基线。有很多工具可以帮助解决这个问题。我使用TestComlete虽然有很好的廉价替代品。

建立了回归测试基线后,我个人就会分而治之,因为根据我的经验,它最有可能成功。一旦有了测试基线,重要的是选择哪种方法。

答案 6 :(得分:1)

对我来说,这取决于具体情况。

如果这是一个非常小的项目,我很想从头开始重写它......但是你通常不会那么奢侈。

如果做不到这一点,我会一点一点地去削减它。我将编写单元测试来验证现有功能,并慢慢使用TDD将代码转换为优雅且设计良好的系统。根据这个过程需要多长时间,它可能会开始看起来像你上面提到的StranglerApplication。

BigBang风险很大,因为你没有简单的方法来验证更新后的系统与旧系统做同样的事情。

Divide and Conquer风险比BigBang低......但如果它的系统足够大,它可能会像BigBang一样有问题。

答案 7 :(得分:0)

总重写是一个选项吗?根据我的经验,从头开始重写通常比尝试清理现有的混乱更有效。您仍然保留现有代码的一部分,但是在新的上下文中。如果你有一个gui和数据库,那也是如此。从头开始重写并带上你可以使用的东西。

答案 8 :(得分:-1)

从一个干净的新架构开始,将旧的代码片段逐个移动到这个新的架构中并重构它以适应新的拱门将是一个不错的选择。我认为在移动函数时采用自下而上的方法会很好。