代码重复的任何正当理由?

sha*_*oth 20 c++ language-agnostic code-duplication

我目前正在审查一个非常古老的C++项目,并在那里看到许多代码重复.

例如,有一个包含5个MFC消息处理程序的类,每个消息处理程序包含10行相同的代码.或者,每个地方都有一个5行代码段用于非常具体的字符串转换.在这些情况下,减少代码重复不是问题.

但我有一种奇怪的感觉,我可能会误解某些东西,并且最初有这种重复的原因.

什么可能是重复代码的正当理由?

Sam*_*Sam 26

关于这一点的一个很好的解读是John Lakos的大规模c ++软件设计.

他对代码重复有许多好处,它可能会帮助或阻碍项目.

最重要的一点是询问何时决定删除重复或重复的代码:

如果此方法将来发生变化,我是否要更改重复方法中的行为,还是需要保持原样?

毕竟,方法包含(业务)逻辑,有时您会想要为每个调用者更改逻辑,有时不会.取决于具体情况.

最后,它是关于维护,而不是关于漂亮的来源.

  • "最后,这完全取决于维护,而不是关于相当来源." < - Mucho importante !! :) (7认同)

Jar*_*Par 16

懒惰,这是我能想到的唯一原因.

更严肃的说明.我能想到的唯一有效理由是产品周期结束时的变化.这些往往受到更多的审查,最小的变化往往具有最高的成功率.在这种有限的情况下,与重构较小的更改相比,更容易获得代码重复更改.

我的口中仍然留下了不好的味道.

  • @Justicle是的,但是当你只想完成那个函数并尝试你的代码时,更容易在那里添加5行代码,而不是考虑传递参数/返回类型以及函数附带的所有其他东西. (4认同)
  • 此外,复制和粘贴方法意味着您根本不必修改原始代码,这意味着破坏某些内容的可能性更小 - 如果您处于发布之前的某个时期,这是一个重要的问题. (3认同)

Dan*_*dor 14

除了缺乏经验之外,还有重复的代码出现可能出现的原因:

没时间进行适当的重构

我们大多数人都在一个真实世界中工作,在这个世界里,真正的约束迫使我们迅速转向真正的问题,而不是考虑代码的优点.所以我们复制并粘贴并继续前进.对我来说,如果我后来看到代码重复了几次,那就是我必须花更多时间在它上面并将所有实例汇总到一个的标志.

由于语言限制,代码的泛化不可能/不"漂亮"

可以说,在函数内部,您有几个语句,这些语句在实例与相同重复代码的实例之间存在很大差异.例如:我有一个为视频绘制2d缩略图数组的函数,它嵌入了每个缩略图位置的计算.为了计算命中测试(从点击位置计算缩略图索引)我使用相同的代码,但没有绘画.

你不确定会有什么概括

首先重复代码,然后观察它将如何演变.由于我们正在编写软件,因此我们可以"尽可能晚地"修改软件,因为所有内容都"软"且可更改.

如果我还记得别的东西,我会添加更多.


稍后添加...

循环展开

在爱因斯坦和霍金合并之前,编译器很聪明,你必须展开循环或内联代码才能更快.循环展开将使您的代码重复,并且可能更快几个百分点,编译器无论如何都不会为您执行此操作.

  • 为你的最后一点+1 - 它与过早优化的原理相同. (3认同)

Joh*_*yre 14

当我第一次开始编程时,我写了一个应用程序,其中我有一些类似的功能,我用一个整齐的小20-30行函数包裹起来......我为自己编写如此优雅的代码而自豪.

不久之后,客户在非常具体的情况下改变了这个过程,然后再次,然后再次,然后又一次又一次地再次......(很多次)我的优雅代码变成了一个非常困难,黑客,越野车,高维护混乱.

一年后,当我被要求做一些非常相似的事情时,我故意决定忽略DRY.我把基本过程放在一起,并生成了所有重复的代码.记录了重复的代码,我保存了用于生成代码的模板.当客户要求特定的条件变更时(例如,如果x == y ^ z + b然后1 + 2 == 3.42),这是一块蛋糕.维护和改变令人难以置信.

回想起来,我可能已经用函数指针和谓词解决了许多这些问题,但是使用我当时的知识,我仍然相信这个特定情况,这是最好的决定.

  • 不断变化的要求是一个杀手.干不是特别的. (13认同)

Lir*_*evi 12

您可能希望这样做以确保一个部分中的未来更改不会无意中更改另一部分.例如考虑

Do_A_Policy()
{
  printf("%d",1);
  printf("%d",2);
}

Do_B_Policy()
{
  printf("%d",1);
  printf("%d",2);
}
Run Code Online (Sandbox Code Playgroud)

现在你可以使用这样的函数来防止"代码重复":

first_policy()
{
printf("%d",1);
printf("%d",2);
}

Do_A_Policy()
{
first_policy()
}

Do_B_Policy()
{
first_policy()
}
Run Code Online (Sandbox Code Playgroud)

但是,某些其他程序员可能希望更改Do_A_Policy()并且通过更改first_policy()来执行此操作,并且会导致更改Do_B_Policy()的副作用,这是程序员可能不知道的副作用.所以这种"代码重复"可以作为一种安全机制来对抗这种未来的程序变化.

  • 这个例子为单元测试而尖叫. (2认同)

cwa*_*wap 6

有时领域方法和类没有任何共同之处,但实现方式看起来很相似.在这些情况下,通常更好的做代码重复,因为未来的更改往往不会将这些实现分支到不同的东西.