长方法在以下几个方面是邪恶的:
- 他们很难理解
- 他们很难改变
- 它们很难重复使用
- 他们很难测试
- 他们的凝聚力低
- 它们可能具有高耦合
- 它们往往过于复杂
如何说服您的开发人员编写简短的方法?(武器是禁止的=)
来自敏捷开发者的问题
长方法在以下几个方面是邪恶的:
如何说服您的开发人员编写简短的方法?(武器是禁止的=)
来自敏捷开发者的问题
要求他们为这些方法编写单元测试。
这取决于您对“短”和“长”的定义。
当我听到有人说“写简短的方法”时,我立即反应很糟糕,因为我遇到了太多的人写的意大利面条,他们认为理想的方法是两行长:一行做尽可能小的工作单元,然后一行调用另一个方法。(你说长方法是邪恶的,因为“它们很难理解”?试着走进一个项目,其中每一个微不足道的动作都会产生一个调用堆栈 50 深的方法,并试图找出这 50 层中的哪一层是你需要更改的...)
另一方面,如果“简短”是指“独立且仅限于单个概念功能”,那么我完全赞成。但请记住,这不能简单地通过代码行来衡量。
而且,正如 tydok 指出的那样,用蜂蜜比用醋捕捉更多的苍蝇。试着告诉他们为什么你的方式是好的,而不是为什么他们的方式不好。如果你可以做到这一点,而无需对他们或他们的实践进行任何公开的比较或引用(除非他们特别询问你的想法与他们正在做的事情有什么关系),它会更好。
你列出了缺点。尝试使用简短的方法列出您将获得的东西。具体例子。然后尝试再次说服他。
我从某处读到这句话:
编写你的代码,就好像必须维护它的人是一个知道你住在哪里的暴力精神病一样。
以我的经验,在这些情况下说服同行的最好方法是通过例子。找机会向他们展示你的代码,并与他们讨论短函数与长函数的好处。最终他们会自然而然地意识到什么是更好的,而不需要让他们感觉“糟糕”的程序员。
代码审查!
我建议您尝试进行一些代码审查。通过这种方式,您可以就最佳实践和公司所遵循的任何格式举办一个小型研讨会。这增加了上下文,即短方法是一种使代码更易读、更容易理解并且符合 SRP 的方法。
如果你试图解释好的设计,但人们只是不明白,或者只是拒绝明白,那就停止尝试。这不值得努力。你得到的只是你自己的坏名声。有些人只是没有希望。
基本上它归结为一些程序员只是不适合开发。他们可以理解已经编写的代码,但他们不能自己创建代码。
这些人应该被引导到支持角色,但不应该允许他们从事任何新的工作。支持是查看许多不同代码的好地方,所以也许几年后他们会看到好的设计的好处。
我确实喜欢其他人建议的代码审查的想法。这些草率的程序员不仅应该审查自己的代码,还应该参与对好的代码的审查。这将使他们有机会了解什么是好的代码。可能他们只是从未见过好的代码。
为了扩展 rvanider 的答案,对代码执行圈复杂度分析确实能引起人们对大方法问题的关注;当我离开时,让人们改变的工作仍在进行中(对大方法的推动力太大)。
引爆点是当我们开始将圈复杂度与错误数据库联系起来的时候。一个超过 20 个非工厂的 CC 保证在 bug 数据库中有多个条目,并且这些 bug 通常具有“血统”(修复 Bug A 导致 Bug B;修复 Bug B 导致 Bug C 等)。实际上,我们有 3 个 CC 超过 100(最多 275 个),这些方法占我们错误数据库中案例的 40%——“你知道,也许 5000 行函数不是一个好主意……”
这在我开始时领导的项目中更为明显。目标是保持 CC 尽可能低(97% 低于 10),最终结果是我基本上停止支持的产品,因为我的 20 个错误不值得修复。
没有错误的软件不会因为短方法而发生(这可能是你必须解决的一个论点),但是错误修复非常快,并且当你使用短方法时通常没有副作用,简洁的方法。
尽管编写单元测试可能会治愈它们的长方法,但您的公司可能不使用单元测试。修辞只到此为止,很少适用于陷入困境的开发人员;向他们展示这些方法如何创造更多的工作和错误的软件。
在函数长度和简单性之间找到正确的融合可能很复杂。尝试应用诸如圈复杂度之类的度量来证明以当前形式维护代码的难度。没有什么比基于分支和决策计数等测试因素的非个人测量更好的了。
不知道这个伟大的报价来自哪里,但是:
“首先,调试的难度是编写代码的两倍。因此,如果你尽可能巧妙地编写代码,那么根据定义,你就不够聪明,无法调试它”
强迫他阅读 Steve McConnell 的 Code Complete。假设每个优秀的开发人员都必须阅读这篇文章。
让他喝醉?:-)
这个答案的重点是一个问题,“为什么我总是写简短的函数,而我不写的时候讨厌自己?”
原因是我难以理解复杂的代码,无论是长函数、维护和操作大量状态的东西,还是诸如此类的东西。多年前我注意到有相当多的人在处理这种复杂性方面比我好得多。具有讽刺意味的是,可能正因为如此,我往往比他们中的许多人更优秀:我自己的局限性迫使我面对和清理那种代码。
很抱歉,我无法在这里真正提供真正的答案,但也许这可以提供一些见解来帮助我们找到答案。
强迫他们阅读“清洁代码”这本书,还有很多其他的,但这是一本新书,很好,而且很容易阅读。
要求他们为复杂代码编写单元测试是一个很好的途径。此人需要亲自了解执行维护或分析时复杂性带来的债务。
我总是问我的团队的问题是:“现在是晚上 11 点,您必须阅读此代码 - 可以吗?您在压力下理解吗?您能否通过电话,无需远程登录,将他们带到他们可以修复的部分一个错误?” 如果答案是否定的,那么接下来是“你能隔离一些复杂性吗?”
如果你得到一个论据作为回报,这是一个失败的原因。然后扔东西。
我会给他们 100 行代码,全部在 1 种方法下,然后另外 100 行代码在几个方法之间划分,并要求他们写下每个方法的解释。
计算写两段所需的时间,然后向他们展示结果。
...确保选择的代码需要两倍或三倍的时间才能理解它是否都在一种方法下 - Main() -
没有什么比通过例子学习更好的了。
短或长是可以不同解释的术语。一个简短的是 2 行方法,而其他人会认为不超过 100 行代码的方法很短。我认为最好声明一个方法不应该同时做超过一件事,这意味着它应该只有一个责任。也许您可以让您的开发人员同行阅读有关如何实践 SOLID 原则的内容。
我通常会向他们展示具有良好编写方法的旧项目。然后,我将逐步介绍这些方法,同时解释我们以这种方式开发它们的原因。
希望在放眼大局时,他们会理解这背后的原因。
附言。此外,这个练习可以结合使用作为旧项目的小型知识转移。
向他展示测试短方法是多么容易。证明编写简短的方法会让他更容易和更快地为他的方法编写测试(他正在测试这些方法,对吗?)
当你审查他的代码时,请提出来。“这个方法比较长,比较复杂,好像在做四件不同的事情。提取方法here , here , here。”
长方法通常意味着对象模型有缺陷,即一个类有太多职责。您可能不希望在同一个类中只需要更多功能,每个功能都更短,而是将这些职责正确分配给不同的类。
教猪唱歌是没有用的。这会浪费你的时间并惹恼猪。
只是比某人更出色。
当需要修复 5000 行例程中的错误时,您将拥有一个 10 行例程和一个 4990 行例程。慢慢地这样做,没有人注意到突然的变化,除了事情开始变得更好并且慢慢地大泥球蒸发了。
你可能想告诉他们他可能有很好的记忆力,但你没有。有些人能够处理比其他人更长的方法。如果你们俩都必须能够维护代码,则只能在方法较小的情况下完成。
只有在他没有优越感的情况下才这样做
[编辑] 为什么这会收集负分?
您可以开始将他们编写的每个方法重构为多个方法,即使他们目前正在处理它们。为您的日程安排分配额外的时间来“重构其他方法以使代码可维护”。像你认为应该做的那样去做,并且——这里是教育部分——当他们抱怨时,告诉他们如果他们第一次就做对了,你就不必重构方法。这样,你的老板知道你必须纠正别人的懒惰,而你的同事也知道他们应该改变它。
这至少是一些理论。