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

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

我不删除的要点是:

  • 代码已经编写完成,工作也已经完成
  • 代码可以在合成环境和真实环境中进行测试
  • 如果组织良好(分组,单独的包,松散耦合等) ,它不会干扰您的整体代码分析或重构
  • 代码可以在将来使用
  • 删除时,作者可能会感到不舒服

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

34463 次浏览

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

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

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

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

  • 对于任何一个新工作的项目,他们不仅必须了解 工作守则,他们必须了解未使用的材料也。这 是浪费时间,制造混乱。

  • 有一个危险,在某个时候,有人会做出改变 无意中涉及“休眠”代码,并可能引入 我知道这发生在我做过的项目上。

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

  • 随着时间的推移,会添加越来越多的旧的未使用代码 这增加了混乱,潜在的 误解与管理费用。

  • 未使用的代码再次被使用的可能性非常小。随着时间的推移,再利用的可能性逐渐减少。如果要删除代码,并且认为代码足够重要,那么可以将代码分支并编写文档。

  • 任何个人的感觉,一个程序员可能有代码,他们可能有 努力工作是可以理解的。但作为专业人士的一部分 需要把这些想法放在一边,让它们变得更好 很好。时间不代表任何人,在工作的代码库中也没有保存历史代码的空间。

@ suspectus 在展示删除代码的原因方面做得非常好; 我想谈谈保留代码的各个要点。

  • 代码已经编写完成,工作也已经完成

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

  • 代码可以在合成环境和真实环境中进行测试

对不起,我不知道你这是什么意思。

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

如果它存在于代码库中,无论组织得多么好,它都会增加维护和理解的负担。的确,它可以被组织成一个负担的 更少,但是如果它消失了,它就不再是负担了。

  • 代码可以在将来使用

在敏捷学校,我们说 YAGNI: 你不需要它。是的,你们 也许吧在未来可能会用到它,但是我们今天对明天的需求了解不够,不能以任何可靠的方式预测它。如果不这么认为,那就是自大倾向于狂妄自大。我们 可以明天所知道的是: 我们希望我们的代码库容易修改,而未使用的代码会减少这一特性。

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

作者必须克服它。我们都曾经写过一些没有用的东西——能够指出一堆正在使用的代码(因为没有使用的代码已经被删除了)比指出一堆你可以说有几个方法的代码要好得多,“而且那个方法实际上正在使用!”

代码已经编写完成,工作也已经完成

这也是没有必要的。如果你不使用它做任何事情,它(根据定义)是无用的,不管它做什么或花费了多少努力。

代码可以在合成环境和真实环境中进行测试

如果它是无用的,那么即使您对它进行了测试,它仍然是无用的。如果代码是无用的,那么对它的测试也应该是无用的(因此保留注释代码会产生歧义——您是否保留测试?如果有注释代码的客户机代码,是否也要注释客户机代码?)

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

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

另一方面,如果代码是 没有组织得很好,那么静态分析、重构和其他任何代码都会被打乱。

您正在给您的工具输入带来噪音,并希望它们能够正确地处理这些噪音。

如果您的静态分析工具计算注释/代码比率会怎样?直到昨天(或者代码被注释的时候) ,你只是把它搞砸了。

最重要的是,注释代码块在理解用于维护和进一步开发的代码方面引入了延迟,而这种延迟几乎总是要付出很大的代价。问问你自己: 如果你需要理解一个函数的实现,你更愿意看什么?两行清晰的代码,还是两行代码和另外26条不再实际的注释?

代码可以在将来使用

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

死代码正在污染你的代码

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

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

我们是由模块化的编码方法驱动的,我们设计的代码是为了与我们的程序员同事交互,而不是为了一台机器。我们应该投入最大的精力,使他/她更容易理解我们的代码。反正机器也没问题。

死代码或注释代码就像是错误的路标,只会让人们感到困惑,所以要不惜一切代价避免它。

  • 恐惧 。这使得团队更加担忧,产出更少。数量 当更多的死代码被引入时,恐惧的指数就会上升 不知道那块是否用过,所以我们不敢移动或触摸它 它。”
  • 如果需要在任何地方改变的东西 在系统中也存在死代码,你改变它吗? 它的 很难知道它是否肯定没有使用的地方,所以它是 总是有风险的。即使不会打破任何东西,死人 代码工作,如果它将采取回来使用后,这个变化?

    当处理一个彻底的改变时,开发人员还必须检查包含代码的每个地方,在死代码的情况下,这是多余的。当代码死亡时,检查它们需要更长的时间,因为很难验证它们是否在任何地方使用。

  • 心理负担每次你需要考虑某事是否是 或者是否应该对死代码进行某些操作 你的一些脑力。
  • “我需要一个关于... ... 的例子 如何使用 Foobar。哦,它在代码库的这些地方。我会吗 检查第一个命中,找出这个在用户界面的位置,嗯..。 到处都找不到
  • 膨胀的报告 (例如有多少行代码、类、例程、更改)。扭曲了项目的可见性以及关于应该处理代码库的哪些部分和对未来项目的估计的决定。
  • 减弱了对代码库的信任。这会导致在冗余任务上花费更多的时间,并打破使用代码库的流程。开发人员可能必须非常仔细地检查他们使用的所有东西是否都能按照他们认为应该的方式工作。

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

但是,如果代码在将来很有可能被使用,那么如果它就在其他代码旁边,而不是在版本控制系统中,那么添加代码就更容易。过了一段时间,您可能不记得代码中的任何单词,因此很难从 VCS 的内部找到代码。但是我会让死代码很少存在,即使那样我也会注释掉这些代码。

你确定代码没用吗?

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

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

积极地删除未使用的代码

你花钱维护代码:

  • 修复破损的构建(工程时间)。我们最近进行了一系列复杂的 #include更改,为未使用的代码引入了一个新的重载,这给几十个开发人员组成的团队中的每个工程师带来了相当大的麻烦。
  • 在测试的机器资源中(假设您有自测试的连续构建)。我的团队最近查看了所有最慢的测试,其中许多测试都是在未使用的代码上进行的。在本地运行测试或作为持续集成的一部分运行测试的工程师正在等待未使用代码上的测试。
  • 在可读性方面(又是工程时间)。头文件表示一个 API。如果它们包含没有人愿意使用但每个人都必须阅读的函数,那么代码的学习曲线就会难得多。
  • 在代码搜索中(又是工程时间)。你会清理你的房子,你的硬盘驱动器,或谷歌驱动器?你搜索一个域名越多,它的相关内容就越重要,以避免误报(或者你使用更复杂的搜索,如网络搜索引擎)。

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

这个讨论已经有好几年了,但我只是偶然遇到..。

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

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

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

对于你的观点。

  • 代码已经编写完成,工作也已经完成

但是它经常需要维护,它也会出现在诸如 find in file 之类的东西中。

  • 代码可以在合成环境和真实环境中进行测试

我不知道你说这个是什么意思。我觉得和上次一样。您的意思是代码已经测试过了,清理它可能意味着需要重新测试。这个成本通常是值得的,因为它将回报90% 的时间,并避免它应该已经清理之前,投入生产。几乎所有的代码都有两个迭代,让它工作,让它干净。原因是必须进行两次测试,因为有人跳过了最后一步。如果你的代码太昂贵,以至于无法校验读取 diff,test (如果它因为大量未使用的代码而变得混乱,那么这就是另一个完整的问题了。

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

无论如何,您的代码应该是这样的,但这只能适度地缓解问题。听到有些东西应该被组织起来却不干净,这是最奇怪的论点。尝试保持代码模块化和减少依赖性是正常的,但是您也想要可重用的代码,如果您的所有模块都是孤立的,那么您可能还没有 DRY。您还可能发现自己进行了过度的解耦操作,除了减轻未使用的凌乱代码的问题之外什么也没有做。

  • 代码可以在将来使用

很多人过于看重编写的代码。如果现在不使用它,它就是自负的,实际上当您沿着这条路径走下去时,通常只有一小部分未使用的代码变成了使用的代码。在所有的概率未使用的代码不可能是可用的或使用的代码。最有可能被重用的代码是已经使用的正在执行某些操作的代码。

更糟糕的是,未使用的代码没有用途。当有人出现,并且不得不修改某些最终影响到未使用代码的东西时,他们将会被难住,坐在那里试图弄清楚这些未使用的代码没有目的地需要做什么。

当开始编写代码需要付出很多努力时,人们很容易有这种感觉。然而,一旦流利并习惯了它的代码就会变得像骑自行车一样。您会发现,随着编写这样一段代码的成本直线下降,保持它的成本也在不断攀升。

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

这是作者的问题。一方面,把大量未使用的代码留给别人处理是自私的。另一方面,如果作者把自己的感受置于代码质量之上,那么他们可能就不应该编写代码。你继续这样下去,你不能修复他们的代码,当它被破坏,因为这会伤害他们的感情。如果某人仅仅因为代码是他们的而不是因为它是好的而依赖于它,这不是一个好的迹象。作者应该为自己的代码被清除而感到高兴。这就像有人帮你倒垃圾,然后扔进垃圾桶。

如果有人为我这么做,我会欣喜若狂的。让你更容易克服这些情绪的方法就是不要等别人来做,而是自己去做。不断迭代地重写你已经完成的一段代码,使它执行得更好,移动简洁,减少多余,更灵活,但每次代码更少。尽量不要对代码的数量感觉良好,而是要看看你能用多少代码实现多少目标。这是磨合水平,一旦你这样做,你所有的代码将出来在一个良好的水平下,所以它不会需要被水平经常。