重写继承的代码比修复它更好吗?

时间:2009-12-10 19:46:39

标签: refactoring

  

可能重复:
  When is it good (if ever) to scrap production code and start over?

假设您已获得一个项目,并查看代码。虽然它有效并且功能正常,但您意识到要进行未来的更改,重写大部分或全部代码会更容易。重写是否更好?如果它现在花费你一个延迟,但以后会延迟你的延迟(以及之后可能的错误修复),是否值得?

或者你只是简单地修复你看到的内容并触及代码的那一部分?

或者只有在报告需要触摸该代码的错误时才修复它?

13 个答案:

答案 0 :(得分:10)

  • 你有多少时间?
  • 你能花多少钱?
  • 您是否完成了投资回报率分析?

经常归结为 money $$

答案 1 :(得分:5)

这取决于代码库的大小。

您是否阅读了this文章?

答案 2 :(得分:4)

十年前我继承了一个代码库。我还在里面,在这里扭曲它,弯曲它。有些部分我有机会彻底改造,而且我几乎总是对结果感到满意。

但有趣的是,经过这么多年,当我回顾最初的代码库时,我必须承认最初的设计还有其他优点,而不是我第一眼看到的。

我的结论?首先尝试完全理解您继承的代码的设计;然后才开始考虑是否需要返工。

答案 3 :(得分:3)

如果要保留当前设计,则应该修复它。如果您决定重写,通常需要进行设计审核。它还取决于产品的预计使用寿命,您可以计划全面重写作为未来版本。

答案 4 :(得分:3)

这是我们许多人面临的一个复杂问题,包括我在内。考虑阅读a good book on the subject,因为这是一个很大的话题。你有多少时间/金钱,你真的了解范围吗?如果(1)您有足够的时间/金钱,并且(2)您确定该解决方案将有足够长的时间来恢复投资,并且(3)你是某些你了解全面改造的范围,那么总改造可能会更好。但那是很多“如果”。

由于时间/金钱限制以及解决方案相关时间的不确定性,零碎重构通常是更好的选择(意思是,降低风险)。您是如何敏捷的?如果您的灵活性和即时设计技巧是您的强项,并且您的客户/老板在此支持您,那么渐进式重构几乎总是更好的选择。

  • 使用与评估编写新代码的准确程度相同的平衡技巧。
  • 将现在花费的时间与可维护性/可测试性/简单性进行比较。
  • 重构最有可能需要调试/修复/重新配置的代码。
  • 不要咀嚼超过你能咀嚼的东西;通常没有很多时间可用于重构。
  • 重构时,单元测试是你最好的朋友。

再次,不要试图做太多!当你的客户/老板问到为什么没有交付功能时,说“好吧,我开始重构一堆东西,并且它引起了很多错误,我仍然试图解决这些问题听起来不太好“。最好只在代码的一个关键部分中保持良好状态。

答案 5 :(得分:1)

我认为作为程序员,重写代码必须更容易适应现有代码,但最终并不意味着最好的解决方案。

Here是一篇有趣的文章:

答案 6 :(得分:1)

这就是重构的全部内容。在不改变其功能的情况下更改现有代码的设计。你说你“意识到”它会更容易重写,但这需要一个假设:你知道将来代码需要什么,你知道重写它会有多少工作,你知道它将重做多少工作。我不知道有哪些程序员是真的(我非常包括在内)。

重构 - 与重写 - 为这种假设提供了一些保护。做得好,你只能按照你今天所需要的东西工作,设计你拥有的代码,以便它可以满足您的迫切需求,然后根据需要进行修改。一点一滴,您的代码变得更清晰,更具有可塑性。改变的那些是需要改变的 - 不会对未来做出不可能的预测。如果你还没有读过Martin Fowler的Refactoring,请看看它;也是Michael Feathers'Working Effectively with Legacy Code

答案 7 :(得分:1)

不要只是根据你的理解开始重写代码。其中有很多经验,隐含要求和错误修复。

相反,在使用它时不断改进代码。尽可能进行单元测试,并寻找机会进行清理。您想要做的事情称为“重构”,这意味着对代码进行相对较小的更改以便以受控方式对其进行改进。重构更改应该足够小,以便您确信它们不会引入错误,单元测试将非常有用。

例如,在我工作的地方,我一直在将一些功能从最初放置的位置(因为它与使用它的例程在同一个类中)移动到另一个类。另一个类相当小,所以它稍微清理了原来的类,它的设计是为了获得功能所需的信息。我一直在这样做。

你永远不会像在某个晚上重写一些无所不知的代码那样干净,但是在那个状态下没有现实世界的代码。要么它是新的和有缺陷的,要么经过测试,至少有些难看。您可以将代码添加到更容易使用的状态。

答案 8 :(得分:1)

Rewrite让您成为管理的目标。我惶恐不安地沿着那条路走下去。

答案 9 :(得分:0)

当我开始当前的工作时,有一个(当时)10年前的C ++应用程序我立即开始工作。

出于各种原因,我们决定重写它并同时保持旧的。

我们仍在努力(5年后)恢复旧应用程序中所有相同的功能,以便我们可以停止维护旧的应用程序。另一方面,我们在新版本中尽早获得了一些功能,这在旧版本中是不可能实现的,因此我们的“客户”并不觉得他们曾经拥有过。如果我们一直工作没有任何东西可以展示它,他们就不会理解(并且会停止支付......)

你甚至可以作弊,并假装在旧框架中可能有的东西是不可能的......谁会与你相矛盾?不,在我们的案例中,我们不得不夸大这种方式...我们真的遇到了技术限制,如果没有重写就无法解决。

答案 10 :(得分:0)

除非有特定需求(例如必须扩展代码的功能超出其原始意图),否则重写代码通常会在混合中引入更多错误。然后你会得到客户的声明:“但它曾经有效......”。

话虽如此,有时候必须这样做。最近,我遇到了两种情况。

答案 11 :(得分:0)

Joel's articles中的一个建议您不要重写代码,因为“旧代码已被使用。它已经过测试。已经发现了很多错误,并且它们已被修复”。

但是我一直处在旧代码最初设计完全错误的情况下,我们认为从长远来看重写它会更好。

答案 12 :(得分:0)

重写起来并不像看起来那么容易,如果你需要在重写过程中维护现有的应用程序,那么你就有可能永远无法匹配现有应用程序的功能,并且总是落后于它。恕我直言,设置流程或改进和重构是更好的,这样当你维护和扩展应用程序时,它会慢慢变得更好,并且更接近理想的设计,如果你能够重写,你可能会想到。

这是一项艰苦的工作。它总是诱人的只是在没有改进的情况下破解新的变化和修复,但我发现如果你可以花费额外的时间来添加一些单元测试,那么你甚至可以慢慢地移动最差的big ball of mud '应用于更容易,更安全的扩展和维护。

我将从以下方法开始:

  1. 制作一份关于您认为当前系统出现问题的高级报告,并从项目发起人那里购买。理想情况下,您可以指出修复“简单错误”或添加“微小新功能”的延迟是由于X问题或Y设计问题造成的。你需要这个,因为改善事情需要时间,你需要能够提醒有权力的人为什么需要额外的工作。你可能需要经常提醒他们......
  2. 确保所有内容都受源代码管理,并且您具有可重复的构建和发布过程。
  3. 在您进行所有未来更改时开始添加单元测试;这最初需要花费更多时间而不是简单地修复 - 每个子系统的前几个测试可能需要花费大量时间才能到位,因为你很可能需要与代码进行一些对抗以使其进入测试工具。坚持不懈,最终还是值得的。
  4. 如果可以,请将更改发布给真实用户。您的发布周期越短,您就越可靠,在进行最后一组更改时,您不会无意中破坏任何内容。如果您已经破坏了某些内容,请添加更多测试并进行修复。
  5. 转到3
  6. 一旦你获得了更多的测试,你将能够自信地重构更多的应用程序。测试将确保您不会破坏现有功能,并在您更改内容时为您提供支持。以这种方式工作的好处是,您将了解现有设计如何挂在一起(并假设它目前提供商业价值,那么您在不破坏价值的情况下这样做。)

    我在2003年以某种方式为一个客户制作了一个系统,并撰写了一些关于它的各个方面的博客文章,它们可能会引起关注,如果您有兴趣可以在这里找到这些帖子的索引:{ {3}}