最佳实践:许多小函数/方法,或具有内联逻辑过程组件的更大函数?

时间:2008-10-30 14:09:57

标签: language-agnostic function

编写许多小方法(或函数)或简单地将这些小进程的逻辑/代码写入您调用小方法的地方是否更好?那么将代码分解为一个小函数呢,即使暂时只从一个地方调用它?

如果一个人的选择取决于某些标准,他们是什么;程序员应如何做出好的判断?

我希望答案通常适用于多种语言,但如有必要,给出的答案可能特定于一种或多种语言。特别是,我正在考虑SQL(函数,规则和存储过程),Perl,PHP,Javascript和Ruby。

12 个答案:

答案 0 :(得分:35)

我总是把很长的方法分解成逻辑块,并尝试用它们制作更小的方法。我不会通常将几行转换为单独的方法,直到我需要它在两个不同的地方,但有时我只是为了帮助提高可读性,或者我想单独测试它。

Fowler的Refactoring就是这个话题,我强烈推荐它。

这是我从Refactoring中使用的一个方便的经验法则。如果一段代码有一条注释,我可以将其重新命名为方法名称,请将其拉​​出来并使其成为方法。

答案 1 :(得分:12)

方法的大小与其cyclomatic complexity直接相关。

保持方法尺寸小的主要优点(这意味着将一个大方法分成几个小方法)是:

  • 更好的单元测试(由于低的圈复杂度)
  • 由于更明确的堆栈跟踪(而不是一个巨大的方法中的一个错误),更好的调试

答案 2 :(得分:9)

一如既往,你可以说:这取决于你。这更像是命名和定义方法任务的问题。每个方法都应该做一个(不是更多)明确定义的任务,并且应该完全完成它们。方法的名称应指明任务。如果您的方法名为DoAandB(),则最好使用单独的方法DoA()和DoB()。如果您需要setupTask,executeTask,FinishTask等方法,则将它们组合起来可能很有用。

有些观点表明,不同方法的合并可能很有用:

  • 不使用其他方法,不能单独使用方法。
  • 您必须小心按正确的顺序调用某些依赖方法。

有些观点表明,方法的拆分可能很有用:

  • 现有方法的某些行有明确的独立任务。
  • 大方法的单元测试会产生问题。如果为独立方法编写测试更容易,那么将大方法拆分。

作为unit-test-argument的解释:我写了一个方法,它做了一些包括IO在内的事情。 IO部分很难测试,所以我想到了。我得出结论,我的方法做了5个逻辑和独立的步骤,其中只有一个涉及IO。所以我将我的方法分成了5个较小的方法,其中4个很容易测试。

答案 3 :(得分:6)

每次都有小方法。

他们是自我记录(呃,如果名字很好)

他们将问题分解为可管理的部分 - 你是KeepingItSimple。

您可以使用OO技术更轻松(并且显然)插入行为。根据定义,大方法更具程序性,因此不太灵活。

它们是可单元测试的。这是杀手,你根本无法对一些执行大量任务的巨大方法进行单元测试

答案 4 :(得分:3)

我从“守则完整”一书中学到的东西:

  • 编写方法/功能以便它 实现一个块(或单元或任务) 逻辑。如果需要细分 进入子任务,然后写一个 单独的方法/功能为他们 并打电话给他们。
  • 如果我找到方法/功能 名字越来越长,然后我尝试 检查方法,看它可以 分为两种方法。

希望这有帮助

答案 5 :(得分:2)

我让每个函数做一件事,只有一件事,我尽量不嵌套太多级别的逻辑。一旦你开始将代码分解为名称好的函数,它就会变得更容易阅读,并且实际上是自我记录的。

答案 6 :(得分:2)

我发现有许多小方法可以使代码更易于阅读,维护和调试。

当我阅读实现某些业务逻辑的单元时,如果我看到一系列描述该过程的方法调用,我可以更好地遵循流程。如果我关心如何实现该方法,我可以查看代码。

感觉就像更多的工作,但它最终节省了时间。

我认为,有一种艺术要知道要封装什么。每个人都有一些意见分歧。如果我可以用文字表达,我会说每种方法都应该做一件可以描述为完整任务的事情。

答案 7 :(得分:1)

一些经验法则:

  • 功能不应超过屏幕上显示的内容
  • 如果使代码更具可读性,则将函数分解为更小的函数。

答案 8 :(得分:1)

方法越大,测试和维护就越困难。我发现当它分解为原子步骤时,更容易理解大型过程的工作原理。此外,这样做是使您的类可扩展的第一步。您可以将这些单独的步骤标记为虚拟(用于继承),或将它们移动到其他对象(组合)中,从而使应用程序的行为更易于自定义。

答案 9 :(得分:1)

我通常会将函数拆分为较小的函数,每个函数执行一个单独的原子任务,但前提是该函数足够复杂以防止它。

这样,我不会为简单任务找到多个函数,而我提取的函数通常可以在别处使用,因为它们不会尝试实现太多。这也有助于单元测试,因为每个函数(作为逻辑,原子动作)可以单独测试。

答案 10 :(得分:0)

就个人而言,我倾向于倾向于选择更多更小的方法,但却没有达到宗教目标的最大线数。我的主要标准或目标是让我的代码保持干净。我有一个重复的代码块(无论是在精神上还是实际上是文本),即使它可能是2或4行,我将该代码干燥成一个单独的方法。如果我认为将来很有可能再次使用它,我有时会提前这样做。

另一方面,我也听说它认为如果你的中断方法太小,在开发团队的背景下,队友可能不会知道你的方法,并且会写内联,或写他的自己的小方法做同样的事情。这无疑是一个糟糕的情况。

有些人还试图争辩说保持内联更具可读性,因此读者可以自上而下阅读,而不必跳过方法定义,可能跨多个文件。就个人而言,我认为堆栈跟踪的存在使得这不是一个问题。

答案 11 :(得分:0)

这取决于心态。不过,这不是一个自以为是的问题。

答案实际上取决于语言环境。

在Java / C#/ C ++世界中,人们遵循罗伯特·马丁(Robert Martin)倡导的“清洁代码”学校,然后:许多小方法都是可行的方法。

一种方法具有明确的名称,并且可以做一件事。就是一层嵌套。它将其长度限制为3、5,最多10行。

老实说:我发现这种编码方式绝对优于任何其他“样式”。

此方法的唯一缺点是您最终会遇到许多小方法,因此在文件/类中进行排序可能会成为问题。但这的答案是使用一个体面的IDE,该IDE可以轻松地前后导航。

因此,使用“所有东西都融合到一个方法/函数中”的唯一“合法”原因是整个团队都这样工作,并且更喜欢这种风格。或者,当您无法使用体面的工具时(但随后浏览该大型丑陋功能也将无效)。