![]() |
1
14
当我第一次开始编程的时候,我写了一个应用程序,在那里我有一堆类似的功能,我用一个简洁的20-30行函数来包装…我为自己写了这么一段优雅的代码而自豪。 不久之后,客户在非常具体的情况下更改了流程,然后一次、一次、一次、一次、一次……(很多次)我优雅的代码变成了一个非常困难,黑客,小车和高维护混乱。 一年后,当我被要求做一些非常类似的事情时,我故意决定忽略dry。我把基本的过程放在一起,生成了所有重复的代码。重复的代码被记录下来,我保存了用于生成代码的模板。当客户要求特定的条件改变时(比如,如果x=y^z+b,那么1+2=3.42),这是小菜一碟。维护和更换非常容易。 回想起来,我可能已经用函数指针和谓词解决了其中的许多问题,但是利用当时的知识,我仍然相信在这个特定的情况下,这是最好的决定。 |
![]() |
2
26
关于这个的一个好消息是 large scale c++ software design John Lakos。 他在代码复制方面有很多优点,在那里它可能有助于或阻碍一个项目。 最重要的一点是在决定删除重复或重复代码时询问: 如果此方法在将来发生更改,我是要更改复制方法中的行为,还是需要保持原样? 毕竟,方法包含(业务)逻辑,有时您需要为每个调用者更改逻辑,有时不需要。视情况而定。 归根结底,一切都是为了维护,而不是为了漂亮的资源。 |
![]() |
3
16
懒惰,这是我唯一能想到的原因。 更严重的是。我能想到的唯一有效原因是在产品周期的最后阶段进行更改。这些计划往往会经受更多的审查,而最小的变化往往具有最高的成功率。在这种有限的情况下,通过代码重复更改比重构较小的更改更容易。 我的嘴里还留着不好的味道。 |
![]() |
4
14
除了缺乏经验外,出现重复代码的原因还有: 没有时间进行适当的重构 我们中的大多数人都是在现实世界中工作的,在现实世界中,真实的约束迫使我们快速地转向现实问题,而不是思考代码的正确性。所以我们复制粘贴并继续。对于我来说,如果我以后看到代码被重复了几次,这就意味着我必须花更多的时间在代码上,并将所有实例聚合到一个实例上。 由于语言约束,代码的泛化不可能/不“漂亮” 假设在一个函数的深处,有几个语句在同一重复代码的实例之间有很大的不同。例如:我有一个为视频绘制二维缩略图数组的函数,它嵌入了每个缩略图位置的计算。为了计算命中测试(从单击位置计算缩略图索引),我使用了相同的代码,但没有绘制。 你不确定是否会有泛化 首先复制代码,然后观察它将如何演变。因为我们正在编写软件,所以我们可以允许对软件进行“尽可能晚”的修改,因为所有东西都是“软”的,并且是可变的。 如果我还记得别的东西,我会再加一点。 稍后添加… 循环展开 在编译器像爱因斯坦和霍金那样聪明的时候,你必须展开循环或者内联代码才能更快。循环展开将使您的代码被复制,而且速度可能快了几个百分点,但无论如何,IT编译器并没有为您做这件事。 |
![]() |
5
12
您可能希望这样做,以确保一部分中的未来更改不会无意中更改另一部分。例如,考虑
现在,您可以使用以下函数来防止“代码重复”:
但是,还有一个风险是,其他程序员可能希望更改do-a-u策略()。 并且通过更改第一个_policy()来实现,并且会导致更改do_b_policy()的副作用,这是程序员可能不知道的副作用。 因此,这种“代码复制”可以作为一种安全机制,防止将来程序中发生这种更改。 |
![]() |
6
6
有时域方面的方法和类没有共同点,但实现方面的方法和类看起来非常相似。在这些情况下,随着未来的变化,代码复制通常会更好,这样就不会将这些实现分支到不相同的地方。 |
![]() |
7
4
我能想到的正当理由是:如果代码变得越来越复杂,以避免重复。基本上,这就是你在几个方法中做几乎相同的事情的地方——但并不完全相同。当然,然后您可以重构并添加特殊参数,包括指向必须修改的不同成员的指针。但是新的重构方法可能会变得过于复杂。 示例(伪代码):
您可以以某种方式重构方法调用(setxxx),但根据语言的不同,这可能很困难(尤其是继承)。这是代码重复,因为每个属性的主体大部分都是相同的,但是很难重构出公共部分。 简而言之,如果重构的方法是更复杂的因素,那么我将使用代码复制,尽管它是“邪恶的”(并且将继续邪恶)。 |
![]() |
8
3
我能看到的唯一“有效”的事情就是当这些代码行不同时,然后通过随后的编辑收敛到相同的代码行。我以前也有过这样的经历,但没有太频繁。 当然,现在是时候将这段代码分解成新功能了。 也就是说,我想不出任何合理的方法来证明重复代码的合理性。看看为什么不好。 这很糟糕,因为一个地方的变化需要多个地方的变化。这会增加时间,有可能出现错误。通过分解它,您可以将代码维护在单个工作位置。毕竟,当你写一个程序时,你不会写两次,为什么一个函数会有什么不同呢? |
![]() |
9
3
对于这种代码复制(很多行重复很多次),我会说:
不过,从我通常看到的情况来看,可能是第一个解决方案:-( 我见过的最好的解决方案是:让开发人员从维护一些旧的应用程序开始,当他们被雇用时——这将教会他们这种事情不好……他们会 理解 为什么,这是最重要的部分。 将代码拆分为多个函数,以正确的方式重新使用代码,所有这些通常都是有经验的——或者您没有雇佣合适的人员;—) |
![]() |
10
2
很久以前,当我使用图形编程时,在某些特殊情况下,您将使用重复的代码,这样可以避免代码中生成的低级JMP语句(它可以通过避免跳转到标签/函数来提高性能)。这是一种优化和执行伪“内联”的方法。 不过,在这种情况下,我不认为这就是为什么他们这么做,呵呵。 |
![]() |
11
2
如果不同的任务是偶然相似的,那么在两个地方重复相同的操作不一定是重复的。如果一个地方的行动发生了变化,那么其他地方的行动也有可能发生变化吗?那么这就是您应该避免或重构的重复。 而且,有时——即使逻辑是重复的——减少重复的成本也太高了。这可能发生,尤其是当它不只是代码复制:例如,如果你有一个数据的记录与特定字段重复在不同的地方自己(DB表定义,C++类,基于文本的输入),通常的方式来减少这种重复是代码生成。这会增加解决方案的复杂性。几乎总是这样,这种复杂性会有回报,但有时不会——这是你要做的权衡。 |
![]() |
12
2
我不知道代码重复的很多好理由,但与其直接着手重构,不如只重构那些您实际更改的代码片段,而不是修改一个您还没有完全理解的大型代码库。 |
![]() |
13
1
听起来原作者要么经验不足,要么时间紧迫。大多数经验丰富的程序员将重用的东西组合在一起,因为以后维护的次数会减少——一种懒惰的形式。 唯一需要检查的是是否有任何副作用,如果复制的代码访问一些全局数据,可能需要进行一些重构。 编辑: 早在编译器很糟糕,优化器甚至更糟糕的时候,由于编译器中的一些错误,人们可能不得不做这样的一个技巧来绕过一个错误。也许是那样?老年多大? |
![]() |
14
1
对于大型项目(代码库大到GB的项目),很有可能 失去 现有的API。这通常是由于文档不足,或者程序员无法定位原始代码,从而导致代码重复。 归根结底就是懒惰,或者糟糕的复习练习。 编辑: 另一种可能性是,在这些方法中可能有一些额外的代码,这些代码在过程中被删除了。 你看过文件上的修订历史了吗? |
![]() |
15
1
所有的答案看起来都是正确的,但我认为还有另一种可能性。 也许有性能方面的考虑,因为您所说的内容提醒我“内联代码”。内联调用它们的函数总是更快的。 也许你看到的代码已经预先处理过了? |
![]() |
16
1
当复制的代码由源代码生成器生成时,我对它没有任何问题。 |
![]() |
17
1
我们发现迫使我们复制代码的是我们的像素操作代码。我们处理非常大的图像,函数调用开销消耗了我们每像素时间的30%。 复制像素操作代码让我们以代码复杂性为代价加快了20%的图像遍历速度。 这显然是一个非常罕见的情况,最终它使我们的源代码显著膨胀(300行函数现在是1200行)。 |
![]() |
18
0
|
![]() |
19
0
在我看来,没有地方可以进行代码复制。例如,看看 this wikipedia article 或者,让我们参考拉里·沃尔的引文:
很明显,代码复制与“懒惰”没有任何关系。 哈哈;) |
![]() |
20
0
由于存在“策略模式”,因此没有复制代码的有效理由。没有一行代码必须被复制,其他的都是史诗般的失败。 |
![]() |
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
![]() |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
![]() |
rainer · 后台插入程序的初始化 1 年前 |
![]() |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
|
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
|
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |