在最近的代 码审查中,我发现一个类中有几行重复逻辑(不到15行)。当我建议作者重构代码时,他辩称那样写的代码更容易理解。但是重新阅读代码后,我必须承认提取重复逻辑可能会影响可读性。
我知道DRY原则只是指导方针,而不是绝对规则。但一般情况下,你是否愿意在追求DRY原则的名义下损害可读性?
在最近的代 码审查中,我发现一个类中有几行重复逻辑(不到15行)。当我建议作者重构代码时,他辩称那样写的代码更容易理解。但是重新阅读代码后,我必须承认提取重复逻辑可能会影响可读性。
我知道DRY原则只是指导方针,而不是绝对规则。但一般情况下,你是否愿意在追求DRY原则的名义下损害可读性?
三次律
第一次做某件事,你只是去做。第二次做类似的事,你会犯错并且觉得重复,但还是会继续重复。第三次做类似的事情,你就需要进行重构。
三次失败就进行重构。
Seibel: 所以对于这些 XII 调用,你写了一个实现。
你有没有发现你积累了许多非常相似的代码片段?Zawinski: 哦,是的,肯定的。通常到第二或第三次复制和粘贴那段代码时,就需要停下来把它放在子程序中。
个人而言,我更喜欢首先让代码易于理解。
DRY的目的在于简化代码的维护。为了消除重复的代码而使代码变得难以理解,在许多情况下会损害代码的可维护性,而不如有一些重复的代码行。
话虽如此,我确实认为DRY是一个好的目标,如果实际可行的话。
我对重复代码毫不容忍。虽然有时因为时间限制等原因可能会出现重复代码,但我仍未找到真正需要重复代码的情况。
称重复代码会影响可读性只是表明你在选择命名方面不够好 :-)
如果所涉及的代码有明确的业务或技术支持目的P,通常应该进行重构。否则,你将面临克隆代码的典型问题:最终你会发现需要修改与P支持相关的代码,但你找不到所有实现它的克隆。
有些人建议将克隆代码数量阈值设为3个或更多个时进行重构。我认为,如果有两个克隆代码,也应该进行重构;在大型系统中,找到其他克隆代码(甚至知道它们可能存在)是很困难的,无论你有两个、三个还是更多。
现在,这个答案是在没有任何能够“找到”克隆代码的工具的情况下提供的。如果你可以可靠地找到克隆代码,那么进行重构的原始理由(避免维护错误)就不那么有说服力了(具有命名抽象的效用仍然是真实的)。你真正需要的是一种可以找到和跟踪克隆代码的方法;抽象它们是一种确保你可以“找到”它们的方法(通过使查找变得微不足道)。
一种能够可靠地找到克隆代码的工具至少可以防止你犯“未更新克隆代码维护错误”的错误。其中一种工具(我是作者)是CloneDR。CloneDR使用目标语言结构作为指导来查找克隆代码,因此无论空白布局、注释更改、变量重命名等都能找到克隆代码(它适用于许多语言,包括C、C++、Java、C#、COBOL和PHP)。CloneDR将在大型系统中查找克隆代码,而不需要任何指导。检测到的克隆代码将被显示出来,以及 antiunifier,这本质上是你可能写的抽象化版本。它的某些版本(针对COBOL)现在已经与Eclipse集成,并在缓冲区内显示你是否正在编辑克隆代码,以及其他克隆代码的位置,以便你可以在那里检查/修订其他克隆代码(你可能会进行重构:)。
我曾经认为克隆就是彻头彻尾的错误,但人们会这样做是因为他们不知道克隆体与原始体的差异,所以在克隆行为发生时最终抽象化并不清晰。现在我相信,如果您可以跟踪克隆体,并在抽象化变得清晰后尝试进行重构,那么克隆是有益的。
在大多数语言中,将块提取到适当命名的方法中很少会影响可读性。
这是您自己的代码,符合您的标准,但我对您的“多少”的基本答案是没有…
你没有说明是哪种语言,但在大多数IDE中,这是一个简单的“重构”->“提取方法”。这样做有多容易,一个带有一些参数的单一方法比两个重复代码块更易于维护。
抽象地说很难确定。但我自己的信仰是,即使只有一行重复的代码,也应该被制作成一个函数。当然,我自己并不总能达到这个高标准。