何时重构


32

我已经阅读了Fowler的Refactoring一书中的大部分内容,并且在过去的大大小小中都重构了许多应用程序。

我发现很难教的一件事是“何时”重构。我倾向于基于过去对我非常有益的直觉。但是,在与人们讨论是应该立即保留一段代码还是现在重构代码时,很难忍受“胆量检查”。

我觉得应该有更严格的方法来解决这个问题,但是不确定它们是什么。

我了解“代码嗅觉”,红色-绿色重构和其他想法,但是我常常觉得,重构的最佳时间不是第一次编写代码,而是第二次或第三次使用代码并意识到这实际上是一个问题,正在实际使用中。


2
本质上,您在问的是与此相同的东西:programmers.stackexchange.com/questions/6268/…。除非您的行动门槛较低,否则成本和风险都较低,对吗?
S.Lott

Answers:


22

当重构成本小于重构成本时进行重构。

可以测量“成本”。例如,代码执行得是否太差,以至于琐碎的错误需要花费数小时或数天才能修复?重构将使您获得更多的客户,或增加容量,或提高性能,从而使现有的客户更快乐吗?


简短和完美
ZJR 2012年

8
换句话说:“值得重构的时候值得重构”。咄。好吧,这不是一个真正的答案,是:) Measure "cost" however you can.-好的,如何?这不是问题的要旨吗?在衡量该成本时应采用什么时间角度?
Konrad Morawski

2
@Morawski:不,这是不正确的措词。我说过,如果从重构中获得的价值大于重构成本,那么重构是值得的。这与说“值得重构时值得重构”不同。计算重构成本。计算不重构的成本。哪个更大?
Bryan Oakley

@BryanOakley:问题是,您无法“计算”这些费用。您最多可以估计它们,这在不重构的成本方面确实很难做到。您对未重构版本和重构版本适用什么维护成本乘数?您如何知道所讨论的代码是否必须维护或更改?您如何估计它将产生的错误数量?最后,我想我们所有人在进行重构时都会无意识地将这些估计作为决策过程的一部分,但是并不能期望其准确性。
guillaume31 '02

1
@ ian31:是的,您无法计算值,而您能做的最好的就是估算。尽管如此,假设您的时间和资源有限,这是决定是否重构的唯一真正有效的方法。您需要确定重构是否值得。如何定义“价值”是一门非常不精确的科学。关键是,您不应该凭直觉来重构-除了“我希望代码更漂亮”以外,应该有充分的理由进行重构。
布莱恩·奥克利

12

  1. 函数的圈复杂度是否低于5?
  2. 您是否完全了解环行复杂性是什么,而无需遵循该链接?
  3. 您是否对该功能的每个路径都有一个自动化测试或有记录的测试用例?
  4. 现有的所有测试用例都通过了吗?
  5. 您能在不到1分钟的时间内向我解释该功能及其所有极端情况吗?
  6. 如果没有,大约5分钟?
  7. 10分钟?
  8. 函数(包括注释)中的代码行是否少于100行?
  9. 您是否可以找到其他两个仅凭肉眼检查就认为该代码没有错误的开发人员?
  10. 此功能仅在一个地方使用吗?
  11. 该功能是否满足其性能目标(时间/内存/ CPU)?

计分

总计上面的“否”答案:

  • 0-1-您为什么还要考虑重构呢?您可能只想重命名变量,因为您不喜欢以前的开发人员的命名约定
  • 2-5-这可能需要一些调整,但对于该范围内的产品,我不会停产
  • 6-8-好的,我们可能需要修复此问题……很可能我们将继续进行修改,并且/或者我们实际上不知道它在做什么。仍然在栅栏上,但高度怀疑
  • 9+-这是重构的主要候选者。(注意,编写测试用例是一种重构形式)

http://mikemainguy.blogspot.com/2013/05/when-to-refactor-code.html


4
#2听起来很势利,实际上对评估代码毫无用处。#3&#4并非每个公司都使用单元测试。#8尽可能避免发表评论,并且100行太高了。我有1台处于纵向模式的大宽屏显示器,几乎无法一次看到整个功能。如果实际代码超过15行,那么应该一直保持这种理由。这是一个不错的实用方法,它具有检查清单,但是这里太多的点是由伪造的,或者使用了随机值而没有任何理由。
R. Schmitz

8

当您的直觉告诉您可能应该进行一些重构时,很可能是您的直觉告诉您您推迟了很长时间已经推迟了一些重要的事情。

我了解“代码嗅觉”,红色-绿色重构和其他想法,但是我常常觉得,重构的最佳时间不是第一次编写代码,而是第二次或第三次使用代码并意识到这实际上是一个问题,正在实际使用中。

重构实际上有两个层次。首先是您第一次编码时出现的明显问题。这些是很少的优化,您无需花太多时间就可以完成。诸如保持您的方法和类较小,并遵守DRY和SRP之类的事情。然后,您需要承担额外的阶段来处理设计中的主要缺陷,直到您的代码下了几英里,这才可能立即显现出来。您正在谈论的是第二层,但是为了确保以后的重构不会太昂贵,您需要已经以某种方式编写了代码,以使以后的工作变得更容易且成本更低,这意味着要尽早进行重构。

正如Jeff在回答中提到的那样,“时间就是金钱”,尤其是在工作量很高且风险更高的公司中。预先花时间确保代码处于最佳状态将在以后节省时间,这在嘲弄原本应该容易进行的重构原来是一项主要操作。

编写软件时,花在真正改进代码上的每一刻都会节省稍后的时间,而这正是您真正需要它的时候。重构越早,以后所做的更改就越清晰。这就像用今天的美元对未来的技术债务支付首付款,而未来的技术债务将在明天的美元膨胀。

在任何情况下,重构都不是您要推迟的任务,直到软件已经完成且稳定的某个神秘的未来为止,因为当风险越来越高且产品难以更改时,重构会增加您的风险。重构应该是您日常活动的一部分,这就是您提到的Red-Green-Refactor哲学的本质。


2

我认为您的问题可以由每个开发人员甚至负责编程的管理人员以不同的方式回答。

我个人的喜好是,每当我学到新知识或改进最佳做法时,我都会重构代码,只要我了解适用于这种情况的最佳标准,便可以立即使代码保持标准。我可以这样做,因为这是一家较小的公司,长期使用相同的软件。

在时间充裕的大型软件开发公司中,可能只是从您从这一点开始学到的更好的实践开始设计,而不必担心在特定软件的版本2之前进行重构?

我觉得教什么时候进行重构确实取决于您目前所在的公司。


2

“何时重构?”

简短答案:每次遇到臭味或可以改善的代码时(童子军规则

实际上,这发生了:

  • 如果您在TDD周期的“重构”步骤中系统地练习TDD,即一旦您的测试呈绿色,则在开始编写新测试之前。
  • 经过代码审查
  • 接管遗留代码时
  • 当使用看起来笨拙的代码时
  • 等等

我觉得这只是说“您应该重构”而没有回答更难的部分:“我觉得应该对此采取更严格的方法,但是不确定它们是什么。”
高度

我不知道该说些什么,只能感觉到维护起来很痛苦,闻到代码气味并利用您的经验。我怀疑是否存在确定的,确定的方法,如果您正在寻找该方法,该方法会告诉您何时何地进行重构。
guillaume31 '02

1

当我第一次学习重构时,我的导师告诉我:“做两次,紧紧抓住鼻子。做三遍。重构。” (感谢Josh!)具体来说,他的意思是,当您第三次编写相同的代码块(甚至是类似的代码模式)时,就是重构的时候了。在过去的10年中,我一直遵循这一原则,并发现它是一个合理的经验法则。

使用Eclipse或具有强大重构支持的类似IDE可以减少进行重构的工作量。IDE支持使您更有可能在达到“第三次”(或看到需要)后立即进行重构,而不是将其视为额外的工作。

另外-TDD在这里也有很大的帮助,因为您可以继续运行测试作为重构,并知道您还没有破坏任何东西。


1

按照其定义进行重构是一个过程。这意味着您不应该努力寻找空闲时间来执行重构任务,而应该在遇到更好编写的代码时始终保持重构。

我个人喜欢编写进化原型,说的更简单:可以正常工作的代码,然后对其进行重构,直到它们达到预期的编码标准为止。另一个很好的例子是添加其他功能并重构现有代码以实现其重用。


1

在我20年的编程生涯中,这是我实际看到的工作的唯一经验法则,人们可以坚持并且管理者有时间去做。(重构就像节食:当然,“卡路里摄入/卡路里消耗”是减肥的秘诀,但这并不能转化为人们会遵守的饮食。)因此:

在您工作时不断重构。使用测试驱动开发,以便一天中有几个红绿色重构周期。仅重构您接触过的部分代码。

一旦您对自己更有把握,就可以选择这种治疗方案。


1

我认为,这取决于项目所有者和对代码质量负责的人的需求。当别人的钱受到质疑时,您根本无法独自决定。

由于技术原因,有几种。

  • 如果您的代码中有错误,则意味着这个地方被误解了,很有可能在这里隐藏更多错误,并且任何尝试开发代码连接部分的问题肯定都会出问题。因此,应检查该位置是否有可能的重构。
  • 另一个原因是当您添加或更改功能时,旧代码对于更改/添加非常不便,而以后的更改/添加很有可能。当然,您应该平衡成本。
  • 也许最严重的原因是当您更改代码且无法测试时。

作为一名Scrum管理员,我们有一个开发人员,他不断争论团队规模的每个故事都比团队想像的要大,并发现意识到他想重构遇到的每段代码。因此,三分的故事对他来说总是八分。显然,这使价值传递更加混乱。因此,某种程度上需要对何时进行重构以及应该如何做出决策有一定的了解。从我(以及其他一些)经历中得出的只是我的想法。
Curtis Reed
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.