你应该多久重构一次?

63

前几周我和一些同事讨论了代码重构的问题,我似乎是少数认为“早重构,常重构”是一个好方法,可以避免代码变得混乱和难以维护。其他人认为这只适用于项目的维护阶段。

如果你有自己的观点,请进行辩护。


8
美国童子军有一条简单的规定“离开营地时比到达时更加清洁”,因此“在归还一个模块之前,始终确保它比借出时更加整洁”。罗伯特·马丁。 - Andrii Abramov
25个回答

83
与您所说的一样:“尽早重构,经常重构。”
早期进行重构意味着需要进行的更改还在我脑海中。经常重构意味着更改往往会更小。
延迟重构只会导致混乱更加严重,从而使重构变得更加困难。一旦注意到混乱,立即清理可以避免其不断累积并成为以后的问题。

37

所有测试通过后,我会立即对代码进行重构。这样我可以在脑海中清晰地记得如何改进它,并且在其他人看到第一版有多丑之前就清理掉。

在最初的提交之后,每次接触代码时我通常都会进行重构。重构不应该是你单独留出时间来做的事情。你应该边做边重构。


2
同意,这也是TDD的一种表达方式:红灯、绿灯、重构! - Jim Deville
我认为这是一个较晚的重构阶段,因为在那个时候你已经被大量的代码束缚住了。 - Marcin
我所说的“代码”,并不是指“应用程序”,而是指模块、类、方法或其他一些小的代码增量。 - Bill the Lizard
你会认为你想要测试重构后的代码,对吧? - Aaron Bush
就像你所说的那样,但如果在重构中出现错误,可能会引入许多新的漏洞。我认为,重构后的代码也需要进行测试。否则,您已经更改了大量的代码,并在没有进行测试的情况下将其释放。 - Aaron Bush
2
@Aaron:测试是重构的一部分。在代码经过测试并通过之前,你不能说你已经完成了。测试是更大过程的一部分,因此明确说明你要测试代码是多余的。 - Bill the Lizard

28
您写代码时需要戴上两顶帽子。一顶是“只要让事情跑起来就行”的帽子,另一顶是“我明天需要理解这个”帽子。显然,第二顶帽子是重构帽子。因此,每当您使某些东西能够工作但(不可避免地)引入了问题,例如重复的代码、冗长的方法、脆弱的错误处理、糟糕的变量名称等等时,您都需要进行重构。
在尝试让某些东西起作用时进行重构(即佩戴两顶帽子)对于非平凡的任务来说并不实际。但是推迟到第二天/下周/下个迭代才进行重构是非常糟糕的,因为您头脑中的问题上下文已经消失了。因此,尽可能频繁地在两个帽子之间切换,但绝不要将它们合并。

太棒了!我会在我的讲座中使用它,说服我的同事重构他们糟糕的代码。 - MartianMartian

19

我尽可能地重构代码,因为这让我能够将代码打磨到最佳状态。即使在主动开发过程中,我也会这样做,以防止一开始就创建难以维护的代码。这通常还可以让我在设计错误变得无法修复之前,将其纠正。


14

重构的三个好处:

  • 原有设计错误(可能是在一个非常小的领域内,但仍然是设计),需要修改。这包括发现一些通用操作并希望共享代码。
  • 进行迭代式设计。
  • 代码质量太差需要进行重大改进。

不重构的三个好处:

  • "这看起来有点杂乱无章"。
  • "我不完全同意上一个人的做法"。
  • "这样可能会更有效率"。(问题是“可能”)

"杂乱无章"是有争议的 - 有一个合理的论点称为“修补破窗户”或“代码卫生”,它建议如果你让小事物滑落了,那么你将开始让大事物滑落。这很好,记住这一点是件好事,但要记住这只是一个比喻。这并不能成为毫无止境地移动代码以寻求最干净的解决方案的借口。

你应该根据好的理由出现的频率和测试过程保护您免受引入缺陷的程度来确定重构的频率。

重构从来不是一个目标。但是如果某些东西不起作用,就必须修复它。这对于初始开发和维护来说都是正确的。对于非平凡的更改,几乎总是比在单个地方打补丁要好得多,而且要避免在其他地方进行任何更改。

值得一提的是,只要我能掌握使用它的内容,并且结果变化的范围可管理,我就会毫不犹豫地更改接口。


7

正如书中所说,当你:

  • 添加一些代码...一个新功能
  • 修复错误/缺陷
  • 进行多人代码审查
  • 发现自己在第三次重复某些内容时...采用3次重复原则

时,你需要进行重构。


“三次打击”在编程界备受争议。请参见http://www.c2.com/cgi/wiki?OnceAndOnlyOnce和http://www.c2.com/cgi/wiki?ThreeStrikesAndYouRefactor。我经历过太多项目因为有人说“再写一遍等等”而受到不利影响的轶事。 - Mike A
1
哈哈,我们需要再多一些评论才能在这个问题上引发争议。 - MartianMartian

7
我试着去遵循这个座右铭:让你接触的所有代码都比之前更好。
当我修复或添加功能时,通常会利用这个机会对受影响的代码进行有限的重构。通常这会使我打算做的更改变得更容易,所以实际上并不需要花费任何成本。
否则,如果你不能因为总是在处理问题而无法分配时间进行重构(我想知道为什么),那么当发现修改变得比它应该更难以及“代码异味”变得不可忍受时,你应该强迫自己进行重构。

6

很多时候,当我在构思想法时,我的代码开始非常紧密耦合和混乱。随着我对想法的不断完善,逻辑分离变得越来越清晰,我开始进行重构。这是一个不断的过程,正如每个人建议的那样,应该“早期和经常”进行。


4

我进行重构的情况有:

当我修改代码时,感到困惑。如果我要花费一段时间才能理清楚它,那就需要进行重构。

当我创建新代码并得到“工作”后。通常情况下,我会让事情运行起来,随着编码的进行,我意识到“嘿,我需要重新做我之前做的20行代码,只不过稍作修改。” 在这个时候我就会进行重构并继续进行。

我认为唯一应该阻止你这样做的是时间限制。无论你喜欢与否,有时候你就是没有足够的时间去做。


我理解你所说的“困惑”,但有时这会让下一个维护人员感到更难处理。他确实理解旧代码,但现在眼前是一个本可以用一行代码处理特殊情况的差异,却要修改文件中的每一行…… - Steve Jessop
@onebyone 如果是这样的话,那么您重构得不正确。重构应该始终提高代码的可维护性。 - Wedge
1
没错。但是即使您通过某种假设的度量标准将代码可理解性提高了50%,因为已经看过以前的代码并且已经理解它的人,在下一次轮到他们查看新代码时也不会发现它更易于理解。 - Steve Jessop
1
此外,易读性对于差异以及修订同样重要。如果可以避免,重构不应与功能更改混合。 - Steve Jessop

4

随时进行重构!只要容易就做。

如果重构很困难,那么你可能选择了错误的时间(代码不需要)或错误的部分(其他地方可以获得更好的效率)。 (或者你还不太擅长重构。)

将重构留到“维护”时期是一种说辞。重构就是维护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接