【问题标题】:Avoiding spaghetti code while writing small functions在编写小函数时避免意大利面条式代码
【发布时间】:2013-08-21 18:56:50
【问题描述】:

我对“意大利面条代码”的理解是一个代码库,它从一个代码块跳转到另一个代码块,没有逻辑和清晰的目的。最常见的违规行为似乎是 GOTO 语句。

我目前正在阅读/参考 Clean Code: A Handbook of Agile Software Craftsmanship 的功能章节。作者虽然承认自己,但对函数的大小非常严格。我理解保持函数较小的想法,但是,他建议它们应该在 5 行左右。虽然类当然变得更加清晰易读,但我害怕通过编写更小的函数来创建意大利面条式代码。较小的函数似乎也无意中创建了更高的抽象。

什么时候代码变成意大利面条代码? 抽象有多抽象?任何答案都会很有帮助。

顺便说一句,尽管这是我第一次发布问题,但我是 Stack Overflow 的长期追随者,因此也欢迎对我的帖子提出任何建议。

非常感谢!

【问题讨论】:

  • 这在程序员交流而不是堆栈上可能会更好。我会投票给你,尽管你即将​​被投票下地狱。
  • 作者给你一个经验法则。但是,没有硬性规定。您可能正在处理需要超过 5 行的算法。但是,当您看到自己重复代码或无法重用现有功能时,是时候进行重构并可能拆分一些功能了。
  • @AMR 感谢您的支持。看了程序员交流之后,我必须同意你的看法。这绝对是一个概念性问题。我很抱歉没有事先弄清楚差异。
  • @Tarik,感谢您的回复。当我阅读这些类型的书籍时,“没有硬性规则”对我来说很快变得显而易见。感谢您的建议,我会牢记重用和重复。
  • 在生活中,你总是需要权衡取舍。您可以在设计应用程序时考虑重用,并创建复杂的 API 以确保无论如何,您都可以轻松插入下一个案例。这需要更多的时间来设计和实施。很难让你的经理相信你正在工作,但没有快速交付那个简单的应用程序。在另一个极端,你编写了一个可以完成这项工作但很难更改的单片代码。你的经理很高兴,你很快就把那个软件弄出来了。然而,当需要对其进行修改或添加功能时,它会变得越来越难。

标签: function coding-style refactoring abstraction


【解决方案1】:

正如 cmets 中已经说过的,没有绝对的规则。最后,您应该以代码的良好可读性为目标。但这不仅仅与您的方法的长度有关。 Robert Martin 建议根据抽象程度对方法进行排序。抽象方法应该在你的类的顶部,方法越多,它的位置就应该越深。

另一个重要方面是方法名称。应该选择好,以明确该方法的作用!如果您明智地选择方法名称,则几乎不需要 cmets。例如,考虑一个 if 语句:

if(isValidAge(value)) {
   ...
}

更具可读性
if(value > 10 && value < 99) {
   ...
}

因为声明的意图变得更加清晰。当然,您可以在第二个示例中添加评论。但是 cmets 经常会过时(Robert Martin 的书中对此有额外的一章)。我认为,这种编程风格导致了许多简短的方法。

很难选择正确的抽象级别。根据我的经验,从低层次的抽象开始更容易。所以我可以先集中精力很好地解决问题。当我以后需要更多抽象时,我仍然可以重构代码。 TDD 有很大帮助!

希望,这会有所帮助...

【讨论】:

  • 最后一段非常同意!
  • 豪普特曼,谢谢您的回答。我同意@Tarik 的观点,您的最后一段确实阐述了如何使用不同的抽象级别。我目前的大多数项目只有低级抽象,您帮助我提高了抽象。尤其是您对 TDD 的引用。完全同意你的看法。你认为我在抽象时如何避免被诅咒的意大利面条代码?
  • 首先,每个班级应该只有一个职责。具有许多职责的类迫使读者经常切换上下文(看看@utnapistim 的答案)。其次,尽量保持公共接口和依赖的数量少。这意味着,您应该使用私有方法。因此,从外部角度来看,您的课程很容易理解。我认为这就像一个防火墙:这个类履行了它的契约,我可以针对它进行测试——不管它在里面看起来是什么。有一套好的测试,你可以改进内在的结构,直到它符合你的审美。
  • 我选择这个作为最合适的答案是因为它提供了一种解决方案,通过只需要外部访问的定义明确的类来避免意大利面条式代码。虽然我想说utnapistim的回答也帮助我理解了如何避免意大利面条代码。
【解决方案2】:

我同意 cmets 和这里的答案。从实践的角度来看,罗伯特马丁在他的书中写的想法每次都是非常好的方向,我试图尽可能地接近这个“规则”,实际上 5 行方法大多不坏。

在我看来,避免意大利面条式代码的最佳方法是编写具有高 Cohesion 的(小)类。缺点是你会变成一堆类,这有时会让新员工进入项目有点困难。

【讨论】:

  • 感谢 Cohesion 的链接。这是我关心的一点:创建小类,使一个类更具可读性,但同事更难维护。尽管 cmets 在解释类和函数的用途方面有很大帮助。 IDE 中的热键还可以帮助开发人员在项目中快速跳转,例如 Command + 鼠标左键单击类或方法将带您进入 Xcode 和 Eclipse 中的原始上下文。感谢您的回复。
【解决方案3】:

我理解保持函数较小的想法,但是,他建议它们应该在 5 行左右。

这听起来很理想:)

虽然类肯定会变得更易读,但我害怕通过编写更小的函数来创建意大利面条式代码。

意大利面条代码是由代码从一个地方跳到另一个地方引起的(在同一个函数中具有不同的抽象级别 - 低级 IO 代码和高级应用程序逻辑)。如果你提取小函数,你的结果会离意大利面条代码更远,而不是更近)。

什么时候代码变成意大利面条代码?

当代码迫使您(程序员)逐行进行心理跳转(切换上下文)时,代码就是意大利面条式代码。无论您是否使用 GOTO 都是如此(但 GOTO 会使问题变得更糟)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多