我多次听说必须从项目中删除未使用的代码。但是,我不清楚“为什么?”。
我不删除的观点是:
- 代码已经写好了,付出了努力
- 代码可以在语法和真实环境中进行测试
- 如果组织良好(分组、单独的包、松散耦合等),它不会干扰您进行整体代码分析或重构
- 将来可能会使用代码
- 删除后,作者可能会感到不舒服
有人可以解释删除(或保留)未使用代码的优点吗?
我多次听说必须从项目中删除未使用的代码。但是,我不清楚“为什么?”。
我不删除的观点是:
有人可以解释删除(或保留)未使用代码的优点吗?
以下是应删除未使用代码的一些原因:
对于任何新参与项目的人来说,他们不仅要了解工作代码,还必须了解未使用的材料。这是浪费时间并造成混乱。
有时会有危险,有人会做出无意中涉及“休眠”代码并可能引入错误的更改。我知道这发生在我从事的项目中。
任何代码的维护都是一种管理负担。通过保留旧的冗余代码,增加了负担。例如,合并主分支中的更改变得更加困难,因为要处理的代码更多,出错的可能性也更大。
随着时间的推移,越来越多的旧未使用代码被添加到代码库中。这增加了混乱、潜在的误解和管理开销。
再次使用未使用的代码的可能性很小。随着时间的推移,重复使用的可能性会降低。如果要删除代码并且认为代码足够重要,则可以将代码分支并记录在案。
编码人员可能对他们可能努力编写的代码有任何个人感受是可以理解的。但是,专业的一部分要求必须将这些想法放在一边,以获得更好的利益。时间不代表任何人,在工作代码库中没有保存历史代码的地方。
@suspectus 在说明删除代码的原因方面做得非常出色;我想解决您个人保留代码的要点。
- 代码已经写好了,付出了努力
但是如果已经编写的代码没有被使用,这只是没有(未来)价值的成本。这是徒劳的努力,保留这些努力的未使用产品并不能验证这些努力。我们保留代码是因为它现在很有用,而不是作为对作者努力的某种纪念。
- 代码可以在语法和真实环境中进行测试
对不起,我不知道你这是什么意思。
- 如果组织良好(分组、单独的包、松散耦合等),它不会干扰您进行整体代码分析或重构
如果它存在于代码库中,无论组织得多么好,都会增加维护和理解的负担。诚然,它可以被组织起来以减轻负担,但如果它消失了,它就根本不是负担。
- 将来可能会使用代码
在敏捷学校里,我们说YAGNI : You Ain't Gonna Need It。是的,您将来可能会用到它,但我们今天对明天的需求了解得不够多,无法以任何可靠性预测它。不这样想是自大趋向于狂妄自大。明天我们可以知道的是:我们希望我们的代码库易于修改,而未使用的代码会损害该特性。
- 删除后,作者可能会感到不舒服
作者必须克服它。我们都写了一些结果证明没用的东西——能够指向一个正在使用的代码体(因为删除了未使用的垃圾)比指向一个你可以说的代码体要好得多一些方法,“而且那个方法确实在使用!”
拿起一些代码并弄清楚意图还不够困难,但现在你必须弄清楚哪些部分没有被使用?
代码已经写好了,付出了努力
这也是不必要的。如果您不将它用于任何事情,那么(根据定义)它是无用的,无论它做了什么或花费了多少精力。
代码可以在语法和真实环境中进行测试
如果它没用,即使您对其进行了测试,它仍然没用。如果代码没用,那么对它的测试也应该没用(因此将注释代码保留在那里会产生歧义-您是否保留测试?如果您有注释代码的客户端代码,您是否也注释了客户端代码? )
如果组织良好(分组、单独的包、松散耦合等),它不会干扰您进行整体代码分析或重构
不是这样。您所有的工具(源代码控制、静态分析、文档提取器、编译器等)都会运行得更慢,因为它们必须处理更多数据(并且这些数据的更大或更小部分是噪音)。
另一方面,如果代码组织得不好,它会搞砸静态分析、重构和其他任何事情。
您正在向您的工具输入引入噪音,并希望它们能够正确处理它。
如果您的静态分析工具计算评论/代码比率怎么办?你只是把它搞砸了,直到昨天(或每当代码被评论时)相关的东西。
最相关的是,注释的代码块会在理解代码以进行维护和进一步开发方面引入延迟,而这种延迟几乎总是会付出很多代价。问问自己:如果你需要了解一个函数的实现,你更愿意看什么?两行清晰的代码,还是两行代码和另外 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);
翻天覆地的变化。如果系统各处都需要更改的东西也存在于死代码中,你会更改它吗?很难知道它是否绝对没有在某个地方使用,所以它总是有风险的。即使它不会破坏任何东西,如果在此更改后将死代码重新使用,它是否会起作用?
在处理彻底的更改时,开发人员还必须检查包含代码的每个地方,如果是死代码,这是多余的。当代码失效时检查它们需要更长的时间,因为很难验证它没有在任何地方使用。
如果您知道代码库的一部分没有被使用,这是非常有价值的,因为您可以将其删除。如果您让它保留,那么将来可能很难或几乎不可能确定它实际上没有被使用。例如,一些以令人惊讶的方式使用代码的东西:反射、动态调用从字符串连接的例程、eval、框架魔术。
但是,如果将来很有可能使用代码,那么如果它就在其他代码中而不是在版本控制系统中,则更容易添加。一段时间后,您可能不记得代码中包含的任何单词,因此很难从 VCS 的内部找到代码。但是我会让死代码很少存在,即使那样我也会将代码注释掉。
死代码正在污染你的代码
死代码降低了可理解性和可读性。
最好的代码总是被重用,如果你有死代码,它会降低可重用性
我们受到模块化编码方法的驱动,我们设计代码是为了与我们的程序员同行进行交互,而不是为机器设计。我们应该尽最大的努力让他/她更容易理解我们的代码。反正机器会好的。
死代码或注释代码就像只会让人们感到困惑的虚假痕迹,所以要不惜一切代价避免它。
这个列表可能看起来很简单,但其中每一个都以数百种不同的方式表现出来,增加了在整个开发过程中协同作用的阻力。效率低下通常可以用直接和数学的方式来证明或证明。
回应你的观点...
但它通常必须维护。它还会出现在文件中查找等内容中。
我不确定你说的这个是什么意思。我觉得和上一个一样。您的意思是代码已经过测试并且清理它可能意味着它需要重新测试。这是一个通常值得的成本,因为它会在 90% 的时间里得到回报,并且避免在投入生产之前应该对其进行清洁。几乎所有代码都有两次迭代,让它工作,让它干净。必须测试两次的原因是有人跳过了最后一步。如果您的代码也太昂贵而无法校对差异,测试(如果它有很多未使用的代码很可能是混乱的)等等,那么这就是另一个完整的问题。
无论如何,您的代码应该是这样的,但这只能适度缓解问题。听到某些东西应该有条理但不干净,这是最奇怪的论点。尝试保持代码模块化并减少依赖是很正常的,但您也需要可重用的代码,如果您的所有模块都是孤岛,那么您可能还没有 DRY。您可能还会发现自己进行了过度的解耦,这只会缓解未使用的混乱代码的问题。
很多人过分重视书面代码。如果现在不使用它,它就是无用的,实际上,当你沿着这条路走下去时,通常只有一小部分未使用的代码会变成使用过的代码。很可能未使用的代码不可能是可用的或已使用的代码。最有可能被重用的代码是已经使用的正在做某事的代码。
更糟糕的是,未使用的代码没有目的。当有人出现并且必须更改最终会影响未使用代码的内容时,他们会坐在那里试图弄清楚这些没有目的的未使用代码需要做什么。
人们在开始时很容易有这种感觉,因为代码需要付出很多努力。然而,一旦流利并习惯了它,代码就像骑自行车一样。你会发现,随着编写这样一段代码的成本直线下降,保持它的成本就会上升。
这是作者的问题。一方面,将大量未使用的代码留给其他人处理是自私的。另一方面,如果作者将他们的感受置于代码质量之上,那么他们可能不应该编码。当你的代码被破坏时,你无法修复他们的代码,因为这会伤害他们的感情。如果某人仅仅因为它是他们的而不是因为它是好的而对代码感兴趣,这不是一个好兆头。作者应该对他们的代码被清理感到高兴。这就像有人为您取出垃圾并将其扔进垃圾箱。
I would be over the moon if someone did that for me. What might make it easier to get over those feelings is instead of waiting for someone else to do it try doing it yourself. Keep iteratively rewriting a piece of code you've done, making it perform better, move concise, with less excess and more flexible yet with less code each time. Try not to feel good about the quantity of code but how much you can achieve with however little code. This is grinding to level up and once you do that all your code will come out at a good level following so it wont need to be leveled as often.
这个讨论已经有好几年了,但我刚刚碰到它......
我没有看到提到的一件事是删除未使用的代码必须进行的工作。在许多情况下,删除未使用的代码所花费的时间和精力本质上并不是微不足道的,而且测试和记录重构的系统通常会产生额外的成本。只是在决策过程中要考虑的另一件事。
首先,您应该始终使用源代码管理工具来管理您的项目,因此删除未使用的代码是一种很好的做法,因为您始终可以使用源代码管理来获取已删除的代码。对我来说,删除未使用代码的原因是只有知道未使用代码的人知道它,团队中的其他人会遇到该代码并尝试弄清楚它的作用以及它如何适合整个应用程序和经过这么多努力以至于根本没有使用代码会感到失望:)
我认为你可以有两种情况: - 应用程序代码:如果它未使用,也许它随着时间的推移未经测试和无人维护,也许你可以转移到“内部代码存储库” - API 代码:如果你正在编写一个库,那么恕我直言更好的选择来维护它,但在您的积极开发过程中
检查代码是否仍然可以编译是不够的。在 C++ 中,如果您删除一个“未使用”的隐式定义方法,就像operator=
您不会遇到编译器错误一样,该类将默默地开始使用(可能不正确的)默认实现。在 Java 或 C# 中,可以通过反射使用代码。在面向对象的语言中,继承可以发挥作用(现在可以调用基类)。几乎在任何语言中,另一个重载函数可能已经接管了。
检查版本控制中代码的使用年限,而不仅仅是未使用。我见过看起来未使用但刚刚提交的代码,实际上是另一个开发人员项目的第一步。
您支付维护代码的费用:
#include
更改链,为未使用的代码引入了新的重载,这给由数十名开发人员组成的团队中的每个工程师带来了相当大的头痛。我想说的是,普通开发人员编写的所有代码在五年内都会被闲置,因此这项活动永远不会停止。不要让这成为你;只写高质量和绝对必要的代码。