有人可以解释删除(或保留)未使用代码的优点吗?


102

我多次听到必须从项目中删除未使用的代码。但是,对我来说“为什么?”还不清楚。

我不删除的观点是:

  • 代码已经写好了,花了很多力气
  • 可以在合成环境和实际环境中测试代码
  • 如果组织得当(分组,单独的软件包,松散耦合的等等),它不会影响您的整体代码分析或重构
  • 将来可能会使用代码
  • 删除后,作者可能会感到不舒服

有人可以解释删除(或保留)未使用代码的优点吗?


16
注释掉的代码也不应属于代码库。
嬉皮

27
因为我们有版本控制。如果我们需要参考旧版本的代码,我们只需回顾一下历史记录即可。
armandino

1
顺便说一句,当项目很大并且某些文件具有> 200修订版本时,提到版本控制可能会很困难
Alex Stamper

22
@AlexStamper,如果您的工具不允许您轻松查看代码的以前版本,则解决方案是获取更好的工具,而不是在源代码中添加噪音。
utnapistim

1
软件工程有一个非常相似的问题
davidvandebunte

Answers:


180

删除未使用的代码的一些原因如下:

  • 对于任何刚从事项目工作的人,他们不仅必须了解工作代码,而且还必须了解未使用的材料。这是浪费时间,造成混乱。

  • 有一种危险,有时某人会做出无意中涉及“休眠”代码并可能引入错误的更改。我知道这是在我从事的项目上发生的。

  • 任何代码的维护都是管理负担。通过保留旧的冗余代码,负担增加了。例如,合并主分支中的更改会变得更加困难,因为有更多的代码需要处理,并且出错的可能性也更大。

  • 随着时间的流逝,越来越多的旧未使用代码被添加到代码库中。这增加了混乱,潜在的误解和管理开销。

  • 再次使用未使用的代码的可能性很小。随着时间的流逝,重复使用的可能性减小。如果要删除代码并且认为代码足够重要,则可以将代码分支出来并进行记录。

  • 编码人员对他们可能会努力工作的代码所产生的任何个人感觉都是可以理解的。但是要成为专业人士,就必须将这些想法放在一边,以求更好。时间代表没有人,在工作的代码库中没有保留历史代码的地方。


26
最近,由于查看未使用的代码(而没有意识到它未使用),我感到生疏。未使用的代码应从存在中剔除!
嬉皮

1
好点,谢谢。我的同事也说了其中的几个
Alex Stamper 2013年

极好的答案。我想在我的硕士论文中引用类似的论点,但似乎找不到合适的资料(书籍,论文等)。你有什么线索吗?
乔纳斯·温克勒

3
我对您刚才拒绝投票的理由非常感兴趣。
2014年

1
还有一点:如果需要再次使用旧代码,那么当今大多数项目都使用SCM,并且可以重新获得代码(有时会进行一些搜索,这是正确的,但正如答案中明确指出的那样,未使用代码被误解的概率为随着年龄的增长,所需的再次减少)。

31

@suspectus在介绍删除代码的原因方面做得非常出色;我想向您介绍一些用于保存代码的项目符号。

  • 代码已经写好了,花了很多力气

但是,如果未使用已编写的代码,那么这只是成本,而没有(未来)价值。付出的努力是徒劳的,并且保留那些努力的未使用产品并不能验证那些努力。我们保留代码是因为它现在很有用,而不是作为对作者工作的某种纪念。

  • 可以在合成环境和实际环境中测试代码

抱歉,我不知道您的意思。

  • 如果组织得当(分组,单独的软件包,松散耦合的等等),它不会影响您的整体代码分析或重构

如果它存在于代码库中,则无论组织得如何好,它都会增加维护和理解负担。诚然,它可以使组织是的负担,但如果它不见了,这是没有包袱可言。

  • 将来可能会使用代码

在敏捷学校中,我们说YAGNI:您将不需要它。是的,您将来可能会用到它,但对于今天的需求,我们今天还不够了解,无法以任何可靠性进行预测。否则认为傲慢自大。我们明天知道的是:我们希望我们的代码库易于修改,而未使用的代码有损于该特性。

  • 删除后,作者可能会感到不舒服

作者必须克服它。我们写的所有东西都证明没有用-能够指向所有正在使用的代码体(因为删除了未使用的内容)要比指向其中的代码体好得多一些方法,“而实际上是在使用它!”


17

挑选一些代码并弄清楚意图是否足够困难,但是现在您必须弄清楚哪些部分没有使用?


14

代码已经写好了,花了很多力气

这也是不必要的。如果您不将其用于任何用途,则它(按定义)是无用的,无论它做了什么或花费了多少精力。

可以在合成环境和实际环境中测试代码

如果没有用,即使对其进行了测试,它仍然没有用。如果代码无用,则对其进行的测试也将无用(因此,将注释的代码保留在那里,会产生歧义-是否保留测试?如果您拥有注释代码的客户代码,那么您是否也注释了客户代码? )

如果组织得当(分组,单独的软件包,松散耦合的等等),它不会影响您的整体代码分析或重构

不是这样 您的所有工具(源代码控制,静态分析,文档提取器,编译器等)将运行速度较慢,因为它们必须处理更多数据(该数据的较大或较小部分是噪声)。

如果代码在另一方面井井有条,它会弄乱静态分析,重构和其他任何。

您正在将噪声引入到工具输入中,并希望它们能够正确应对。

如果您的静态分析工具计算注释/代码比率怎么办?您只是把它弄乱了,直到昨天才有意义(或者在注释了代码的任何时候)。

最重要的是,带注释的代码块会延迟理解代码以进行维护和进一步开发的时间,而这种延迟几乎总是会花费很多。问问自己:如果您需要了解功能的实现,那么您宁愿看什么?两行清晰的代码,或两行代码和另外二十六个不再实际的注释?

将来可能会使用代码

如果是这样,您将在团队的首选SCM中找到它。

如果您使用合格的SCM并依靠它来保存无效代码(而不是使源混乱),那么您不仅应该看到谁删除了该代码(提交作者),还应该看到由于什么原因(提交消息)以及其他原因随之而来的是更改(该提交的其余差异)。

删除后,作者可能会感到不舒服

所以?

您(我假设)是整个开发人员团队,他们的薪水是制作您知道如何做的最好的软件,而不是“在不损害X感受的情况下您知道做的最好的软件”。

这是编程的一部分,大多数编写的代码最终都将被丢弃。例如,乔尔·斯波尔斯基(Joel Spolsky)曾说过,在他的公司中,大约有2%的书面代码可以生产。

如果您将开发人员的自我优先于代码库的质量,那么您将牺牲产品的质量,因为……到底是什么?保留开发人员的不成熟状态?保护同事的不切实际的期望?

编辑:我已经看到了将注释掉的代码留在源代码中的一个正当理由,这是一个非常特殊的情况:当代码以怪异/不直观的形式编写并且以干净的方式重写时,代码并没有工作的原因非常微妙。仅在反复尝试纠正此问题之后,并且每次尝试重新引入相同的缺陷后,才应应用此方法。在这种情况下,您应该添加注释后的直观代码作为注释,并解释为什么它不起作用(这样以后的开发人员将不会再次尝试相同的更改):

// note by <author>: the X parameter here should normally
// be a reference:
// void teleport(dinosaur& X);
// but that would require that we raise another dinosaur and
// kill it every twelve hours
// as such, the parameter is passed by value
void teleport(dinosaur X);

10

无效代码正在污染您的代码

死代码会降低可理解性和可读性。

最佳代码始终会被重用,如果您的代码无效,则会降低可重用性

我们由模块化的编码方法驱动,在该方法中,我们设计代码以与我们的其他程序员交互,而不是为机器交互。我们应该尽最大努力使他/她易于理解我们的代码。机器还是可以的。

无效或注释不清的代码就像是错误的痕迹,只会使人感到困惑,因此不惜一切代价避免使用它。


10
  • 恐惧。这使团队更加担心而产生更少的东西。当引入更多死代码时,恐惧的数量呈指数增长。“我们不知道该位是否被使用,因此我们不敢删除或触摸它。”
  • 彻底的变化。如果无效代码中还存在系统中各处需要更改的内容,您是否要进行更改?很难确定它是否绝对不在某处使用,因此始终存在风险。即使它不会破坏任何内容,但如果在更改后将其重新使用,则无效代码将完全起作用吗?

    在进行彻底更改时,开发人员还必须检查包含代码的每个位置,对于无效代码,这是多余的。在代码失效后,检查它们会花费更长的时间,因为很难验证是否在任何地方都没有使用它。

  • 心理负担。每当您需要考虑是否使用某些东西或是否应该对无效的代码进行处理时,这都需要您的一些脑力。
  • 野鹅追逐。“我需要一个有关如何使用Foobar的示例。哦,它位于代码库中的这些地方。我将检查第一个匹配项,并找出它在UI中的位置。嗯……在任何地方都找不到。”
  • 夸大的报告(例如,多少行代码,类,例程,更改)。扭曲了项目的可见性,以及有关应在代码库的哪些部分上进行工作的决策以及对未来项目的估计。
  • 对代码库的信任度下降。这可能会导致在冗余任务上花费更多的时间,并且会中断使用代码库的流程。开发人员可能必须非常仔细地检查,以确保他们使用的所有内容都能按照他们认为的方式工作。

如果您知道未使用代码库的一部分,这将非常有价值,因为您可以将其删除。如果保留它,那么将来很难或几乎不可能确定它实际上未被使用。例如,某些以令人惊讶的方式使用代码的事物:反射,动态调用由字符串连接的例程,eval,框架魔术

但是,如果将来很有可能会使用代码,则将其添加到其他代码中而不是在版本控制系统中,则更容易添加。您可能忘记了一段时间后代码中没有的任何单词,因此很难从VCS的肠道中找到代码。但是我会让死代码很少存在,即使那样我也会注释掉代码。


4
  • 未使用的代码为您提供了更大的搜索空间,您可以通读它,也可以浏览通常扫描您代码的其他任何内容。例如,编译器,IDE,文件查找,调试,静态分析,更多内容用于审阅,文件包含,从VCS中签出等。这会减慢这些过程的速度,并增加很多噪音。
  • 未使用的代码并不总是死代码。它可能在某些情况下执行。这不仅可以提供错误和性能问题的解决方案,而且还可能引起安全问题。在性能方面,这可能会以意想不到的方式表达自己,例如较大的下载量。
  • 未使用的代码会生成未使用的代码。如果删除一个函数调用,然后搜索该函数的用途以查看是否仍需要该函数,则可能会看到与先前未使用的代码匹配,并假定您可以保留它。您未使用的代码越多,确定代码是否未使用的跃点就越多。
  • 未使用的代码仍然经常不得不维护。假设A和B取决于C。在那些B中没有使用。您更改了C,然后B无法编译,因为您已从B中所需的C结构中删除了一个成员,现在您必须修复B或将其主动从编译中删除。您应该只删除了它。

这个列表看似简单,但是每一个都以数百种不同的方式表现出来,从而增加了在整个开发过程中协同作用的阻力。效率低下通常可以直接和数学的方式证明或证明。

为了回应您的观点...

  • 代码已经写好了,花了很多力气

但是它通常必须维护。它还会显示在文件查找等内容中。

  • 可以在合成环境和实际环境中测试代码

我不确定这是什么意思。我认为与上一个相同。您的意思是代码已经过测试,清理代码可能意味着它需要重新测试。这是通常值得的成本,因为它将在90%的时间内还清,并避免在投入生产之前应进行清洁。几乎所有代码都有两次迭代,使其工作并使其干净。之所以必须进行两次测试,是因为有人跳过了最后一步。如果您的代码也太昂贵以至于无法读取差异,请进行测试(可能是因为很多未使用的代码太杂乱了),等等,这就是另外一个完整的问题。

  • 如果组织得当(分组,单独的软件包,松散耦合的等等),它不会影响您的整体代码分析或重构

无论如何,您的代码都应该像这样,但这只能适度缓解问题。听到某些东西应该组织得还不干净,这是最奇怪的说法。尝试保持代码模块化并减少依赖关系是正常的,但是您也想要可重用的代码,并且如果所有模块都是孤岛,那么您可能还没有干过。您可能还会发现自己进行了过多的去耦,但是却无济于事,从而减轻了未使用的混乱代码的问题。

  • 将来可能会使用代码

许多人看重编写代码。如果现在不使用它,它将是无谓的,实际上,当您沿这条路走时,通常只有一小部分未使用的代码成为已使用的代码。极有可能未使用的代码不太可能是可用或已使用的代码。最可能被重用的代码是正在使用的正在执行某些操作的代码。

更糟糕的是,未使用的代码没有目的。当有人出现并不得不更改某些东西而最终影响未使用的代码时,他们将被困在那儿,试图找出这些未使用的代码是什么目的而无需做的。

人们在开始时很容易感觉到这种情况,因为代码需要大量的精力。但是一旦流利并习惯了,代码就会变得像骑自行车一样。您会发现,编写这样一段代码的成本直线下降,而使代码不断攀升的成本却越来越高。

  • 删除后,作者可能会感到不舒服

这是作者的问题。一方面,将大量未使用的代码留给其他人处理是很自私的。另一方面,如果作者将自己的想法放在代码质量之上,那么他们可能不应该编写代码。这样做会导致代码损坏时无法修复他们的代码,因为这会伤害他们的感受。如果有人仅仅因为代码是他们的而不是代码的好而附加了代码,这不是一个好兆头。作者应该为自己的代码被清理感到高兴。这就像有人为您取出垃圾并扔进垃圾箱。

如果有人为我做的话,我将过月。可能更容易克服这些感觉,而不是等待别人去做,而是自己尝试做。不断迭代地重写已完成的一段代码,使其性能更好,简洁明了,多余更少,更灵活,但每次代码更少。尽量不要对代码量感到满意,而只需很少的代码就可以实现多少。这正在逐步升级,一旦完成,您的所有代码都会以良好的水平出现,因此不需要经常进行升级。


3

首先,您应该始终使用源代码管理工具来管理您的项目,因此删除未使用的代码是一个好习惯,因为您始终可以使用源代码管理来获取已删除的代码。对我来说,删除未使用的代码的原因是,只有知道该代码未使用的人员才知道该代码,团队中的其他人会遇到该代码,并试图找出它的作用以及它如何适合整个应用程序,以及经过大量的努力后,您将感到失望,以至于根本没有使用该代码:)


3

这个讨论已经有好几年了,但是我碰到了...

我没有看到的一件事是删除未使用的代码必须进行的工作。在许多情况下,删除未使用的代码的时间和精力在本质上并不是微不足道的,而且通常还会有额外的成本来测试和记录重构的系统。在决策过程中要考虑的另一件事。


2

我认为您可能有两种情况:-应用程序代码:如果未使用它,或者经过一段时间未经过测试和维护,也许您可​​以转到“内部代码存储库”-API代码:如果您正在编写库,那么恕我直言维护它的更好选择,但是要在您的积极开发过程中进行


2

您确定代码未使用吗?

仅检查代码是否仍可编译还不够。在C ++中,如果删除“未使用”的隐式定义的方法(operator=不会出现编译器错误),则该类将仅默默地开始使用(可能不正确)默认实现。在Java或C#中,可以通过反射使用代码。在面向对象的语言中,继承可以发挥作用(现在可以调用基类)。在几乎所有语言中,另一个重载函数都可能已被接管。

在版本控制中检查代码的使用期限,而不仅仅是检查是否未使用。我看到过看起来未使用但刚刚提交的代码,实际上这是另一个开发人员项目的第一步。

积极删除未使用的代码

您需要支付维护代码:

  • 修复损坏的构建(工程时间)。最近,我们进行了一个复杂的#include变更链,为未使用的代码引入了新的重载,这导致数十名开发人员团队中的每个工程师都感到相当头痛。
  • 在机器资源上进行测试(假设您具有自测试的连续版本)。我的团队最近查看了我们所有最慢的测试,其中许多测试都是未使用的代码。在本地或作为持续集成的一部分运行测试的工程师正在等待未使用代码的测试。
  • 在可读性方面(再次设计时间)。您的头文件代表一个API。如果它们包含没人愿意使用但每个人都必须阅读的功能,那么代码的学习难度就大得多。
  • 在代码搜索中(再次工程时间)。您会打扫房子,硬盘或Google云端硬盘吗?搜索域名的次数越多,拥有相关内容以避免误报的重要性就越大(或者您使用网络搜索引擎等更复杂的搜索)。

我想说的是,平均每个开发人员编写的所有代码在五年的时间里都不会使用,因此这项活动永远不会停止。不要让这个成为你;只写高质量和绝对必要的代码。

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.