为什么要删除未使用的代码?

时间:2013-03-29 08:44:53

标签: refactoring

我多次听说过必须从项目中删除未使用的代码。 然而,我不清楚“为什么?”。

我不删除的要点是:

  • 代码已编写,并且已花费精力
  • 可以在同步和真实环境中测试代码
  • 如果组织良好(分组,单独的包,松散耦合等),它不会干扰您对整体代码分析或重构
  • 以后可能会使用代码
  • 删除后,作者可能会感到不舒服

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

提前致谢!

11 个答案:

答案 0 :(得分:147)

以下是应删除未使用代码的一些原因:

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

  • 有时会有人做出改变 它无意中涉及“休眠”代码并且可以引入 错误。我知道这件事发生在我参与过的项目上。

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

  • 随着时间的推移会发生越来越多的旧未使用代码 到代码库。这增加了混乱,潜力 误解和行政管理费用。

  • 很可能再次使用未使用的代码。随着时间的推移,重复使用的可能性会减少。如果要删除代码并且认为代码足够重要,那么代码可以分支并记录。

  • 编码员可能对他们可能拥有的代码有任何个人感受 努力工作是可以理解的。但是专业的一部分 要求必须将这些想法放在一边,以便更好 好。时间代表没有人,没有地方可以在工作的代码库中保留历史代码。

答案 1 :(得分:22)

@suspectus在介绍删除代码的原因方面做得非常出色;我想解决你的个别子弹用于保存代码。

  
      
  • 代码已编写,并且已花费精力
  •   

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

  
      
  • 可以在同步和真实环境中测试代码
  •   

对不起,我不知道你的意思。

  
      
  • 如果组织良好(分组,单独的包,松散耦合等),它不会干扰您对整体代码分析或重构
  •   

如果它存在于代码库中,无论组织得多好,它都会导致维护和理解负担。没错,它可以被组织起来以减轻负担,但如果它已经消失,那就没有任何负担了。

  
      
  • 以后可能会使用代码
  •   

在敏捷学校,我们说YAGNI:你不需要它。是的,您可能将来可能会使用它,但我们今天对于明天的需求能够用任何可靠性预测它都知之甚少。不这么认为是傲慢倾向于狂妄自大。我们可以明天知道的是:我们希望我们的代码库易于修改,而未使用的代码会减损该特性。

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

作者必须克服它。我们所写的所有内容都证明没有用 - 更好的是能够指向所有正在使用的代码体(因为未使用的cruft被删除)而不是代码体,你可以说一些方法,“那个实际上正在使用!”

答案 2 :(得分:14)

拾取一些代码并弄清楚意图是不是很难,但现在你必须弄清楚哪些部分没有被使用?

答案 3 :(得分:13)

  

代码已经编写,并且已经付出了努力

这也是不必要的。如果你不把它用于任何东西,它(按照定义)是无用的,无论它做什么或花了多少精力。

  

可以在同步和真实环境中测试代码

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

  

如果组织良好(分组,单独的包,松散耦合等),它不会干扰您对整体代码分析或重构

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

另一方面,如果代码井井有条,那么它将会破坏静态分析,重构和其他任何内容。

您正在为工具输入引入噪音,并希望他们能正确应对它。

如果您的静态分析工具计算评论/代码比率怎么办?你刚搞砸了,直到昨天(或每当代码被评论时)都有相关的东西。

最重要的是,评论的代码块导致了解维护和进一步开发代码的延迟,并且这种延迟几乎总是花费很多。问问自己:如果你需要了解一个函数的实现,你还需要看一下什么?两行清晰代码,或两行代码和另外二十六条不再实际的注释?

  

以后可能会使用代码

如果是,您将在您选择的团队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);

答案 4 :(得分:9)

  • 恐惧即可。这使得团队更加担心并减少生产。数量 当引入更多死代码时,恐惧会以指数方式上升。 “我们 不知道是否使用了该位,所以我们不敢删除它或触摸 它。“
  • 彻底改变。如果需要在任何地方改变某些事情 在系统中也存在死代码,你改变它吗?它的 很难知道它是否绝对不会在某处使用,所以它就是 总是风险。即使它不会破坏任何东西,死者也会 代码是否可以在此更改后重新使用?

    在处理彻底更改时,开发人员还必须检查包含代码的每个位置,如果是死代码,则这是多余的。当代码死了,检查它们需要更长的时间,因为很难验证它在任何地方都没有使用过。

  • 心理负担。每次你需要考虑是否有事情 使用或是否应该对死代码执行某些操作 你的一些脑力。
  • 野鹅追逐。 “我需要一个例子 如何使用Foobar。哦,它在代码库中的这些地方。生病 检查第一个匹配并找出它在UI中的位置。嗯... 无法在任何地方找到它。“
  • 夸大的报告(例如,有多少行代码,类,例程,更改)。扭曲项目的可见性,决定应该对代码库的哪些部分进行处理以及对未来项目的估计。
  • 削弱了对代码库的信任。这可能会导致更多时间花在冗余任务上,并且会破坏使用代码库的流程。开发人员可能必须非常仔细地检查他们使用的所有内容是否会以他们认为应该的方式工作。

如果你知道没有使用代码库的一部分,那么它是非常有价值的,因为你可以删除它。如果你让它留在那么将来很难或几乎不可能确定它实际上没有被使用。例如,一些以令人惊讶的方式使用代码的东西:反射,动态调用例程从字符串连接起来,eval,框架魔法

但是,如果将来很有可能会使用代码,那么如果它在其他代码中而不是版本控制系统中,则更容易添加。您可能不记得代码在一段时间后出现的任何单词,因此很难从VCS的内容中找到代码。但是我很少让死代码存在,即便如此我也会对代码进行评论。

答案 5 :(得分:7)

死代码正在污染您的代码

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

最好的代码总是被重用,如果你有死代码,它会降低可重用性

我们受模块化编码方法的驱动,我们设计代码与我们的程序员进行交互,而不是机器。我们应该投入最大的精力让他/她理解我们的代码。无论如何,机器都会很好。

死亡或评论的代码就像虚假的痕迹,只会让人迷惑,所以不惜一切代价避免它。

答案 6 :(得分:3)

  • 未使用的代码是一个更大的搜索空间,供您阅读以及通常扫描代码的任何其他内容。例如编译器,IDE,文件查找,调试,静态分析,更多审查,文件包含,从VCS签出等等。这会减慢这些过程并增加大量噪音。
  • 未使用的代码并不总是死代码。它可能在某些情况下执行。这不仅可以提供错误和性能问题的向量,还可以是安全问题。在性能方面,这可能会以意想不到的方式表现出来,例如更大的下载量。
  • 未使用的代码会导致未使用的代码。如果您删除了一个函数调用,然后搜索该函数的使用,以查看它是否仍然需要,您可能会看到以前未使用的代码匹配并假设您可以保留它。您使用的代码越多,确定代码是否未使用的跳数就越多。
  • 未使用的代码通常最终必须维护。假设A和B依赖于C.在那些B中没有使用。你改变C然后B不会编译,因为你已经从B中需要的C中的结构中删除了一个成员,现在你必须修复B或者从编译中主动删除它。你应该简单地删除它。

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

回应你的观点...

  • 代码已编写,并且已花费精力

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

  • 可以在同步和真实环境中测试代码

我不确定你的意思。我认为它与最后一个相同。你的意思是代码已经过测试并且清理它可能意味着它需要重新测试。这通常是值得的,因为它将在90%的时间内得到回报,并避免在投入生产之前应该进行清理。几乎所有代码都有两次迭代,使其工作,使其干净。原因是必须进行两次测试是因为有人跳过了最后一步。如果您的代码也太昂贵,无法证明读取差异,测​​试(可能是因为很多未使用的代码很乱),那么这又是一个完整的问题。

  • 如果组织良好(分组,单独的包,松散耦合等),它不会扰乱您的整体代码分析或重构

无论如何,您的代码应该是这样的,但这只能适度地缓解问题。听到某些事情应该有条不紊而且不洁净是最奇怪的论点。尝试保持代码模块化并减少依赖性是正常的,但是您还需要可重用的代码,如果您的所有模块都是孤岛,那么您是否还没有干。您可能还会发现自己做了过多的解耦,除了缓解未使用的凌乱代码问题之外什么都不做。

  • 以后可能会使用代码

很多人超值写代码。如果它现在没有被使用它的载重量,实际上当你走这条路时,通常只有一小部分未使用的代码被用作代码。很可能未使用的代码不太可能是可用的或使用过的代码。最可能被重用的代码已经被用于执行某些操作的代码。

更糟糕的是,未使用的代码没有用处。当有人出现并且不得不改变最终会影响未使用的代码的东西时,他们会坐在那里试图弄清楚这些未使用的代码没有任何目的需要做什么。

当开始代码需要付出很多努力时,人们很容易感觉到这一点。然而,一旦流畅,习惯了它就像骑自行车一样。你会发现,编写这样一段代码的成本会随着成本的下降而大幅下降。

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

这是作者的问题。一方面,留下大量未使用的代码以供其他人处理,这是自私的。另一方面,如果作者将他们的感受置于代码质量之上,那么他们可能不应该编码。你可以通过这种方式解决问题,因为它会损害他们的感情。如果某人仅仅因为它是他们的而不是因为它是好的而附加到代码,这不是一个好兆头。作者应该对他们正在清理的代码感到高兴。这就像有人为你拿垃圾并把它丢进垃圾箱。

如果有人为我这样做,我会登上月球。什么可以让你更容易克服这些感受,而不是等待别人去尝试自己做。继续迭代地重写您已完成的一段代码,使其表现更好,移动简洁,少用多余,更灵活,每次只需更少的代码。尽量不要对代码的数量感觉良好,但是无论代码多么少,您都可以实现多少代码。这是为了提升水平,一旦你这样做,你的所有代码都会以很高的水平出现,所以不需要经常调平。

答案 7 :(得分:2)

首先,您应始终使用源代码管理工具来管理项目,因此删除未使用的代码是一种很好的做法,因为您始终可以使用源代码控制来获取已删除的代码。对我来说,删除未使用的代码的原因是只有知道代码的人才知道它,团队中的其他人会遇到该代码并试图弄清楚它的作用以及它如何适合整个应用程序和经过这么多的努力,代码根本就没用了会感到很失望:)

答案 8 :(得分:2)

我认为你可以有两种情况:   - 应用程序代码:如果未使用它可能是未经测试且未经过时间分配,也许你可以转移到“内部代码库”   - API代码:如果你正在编写一个库,那么恕我直言,它是一个更好的选择来维护它,但在你的活跃开发过程中

答案 9 :(得分:2)

您确定代码未使用吗?

检查代码仍然编译是不够的。在C ++中,如果删除像operator=这样的“未使用”implicitly defined method,则不会出现编译错误,该类将默默地开始使用(可能不正确的)默认实现。在Java或C#中,可以通过反射使用代码。在面向对象的语言中,继承可以发挥作用(现在可以调用基类)。在几乎任何语言中,另一个重载函数可能已经接管了。

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

积极删除未使用的代码

您付费维护代码:

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

我会说基本上开发人员编写的所有代码在五年内都没有使用,所以这个活动永远不会停止。不要让这个成为你;只写高质量和绝对必要的代码。

答案 10 :(得分:2)

这个讨论已有几年了,但我刚刚遇到它......

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