一个函数应该有多短?

时间:2011-01-14 00:09:18

标签: function memory memory-management semantics

我在这里做了一些搜索,并没有发现任何类似的东西,所以我要继续问问。这实际上更多地是关于语义而不是实际的编程问题。我目前正在用C ++编写一些东西,但语言并不重要。

我很清楚,保持您的功能/方法尽可能短是一种很好的编程习惯。然而,你怎么知道函数是否太长?或者,是否有可能将功能分解太多?

我学到的第一种编程语言(除了Applesoft BASIC,不计算......)是6502汇编语言,其中速度和优化就是一切。如果一些循环计数会搞砸整个程序的时间,通常最好直接设置内存位置或寄存器,而不是跳转到另一个子程序。前一种操作可能需要3到4个周期,而后者可能需要两到三次。

虽然我意识到现在如果我甚至向某些程序员提及循环计数,他们只是给我一个空白的外观,这是一个很难打破的习惯。

具体来说,让我们说(再次使用C ++)我们有一个私有类方法,如下所示:

int Foo::do_stuff(int x) {
    this->x = x;
    // various other operations on x
    this->y = this->x;
}

我见过一些论据,至少,每组操作都应该是它自己的功能。例如,do_stuff()理论上应该被命名为set_x(int x),应该为在类成员x上执行的操作集编写一个单独的函数,并且应该编写第三个函数来分配类成员的最终值。 x到班级成员y。但我已经看到其他论点,即每个操作都应该有自己的功能。

对我而言,这似乎是错误的。我再一次从内部角度看问题;每个方法调用都在推送堆栈上的地址,执行其操作,然后从子例程返回。对于相对简单的事情来说,这似乎是一个很大的开销。

对于这类事情是否有最佳做法,还是更多取决于个人判断?

5 个答案:

答案 0 :(得分:8)

自6502汇编以来,发生了两件事:计算机速度更快,编译器(适当时)变得更聪明。

现在的建议是停止花费你所有的时间来讨论个别周期,,直到你确定它是一个问题。你可以更明智地度过那段时间。如果你向我提及周期盘点,我不会茫然地看着你,因为我不知道它们是什么。我会看着你想知道你是否在浪费你的努力。

相反,开始考虑让你的功能足够小,以便:

  • 可以理解的,
  • 可测试的,
  • 也许,可以在适当的地方重复使用。

如果稍后您发现某些代码运行速度不够快,请考虑如何对其进行优化。

注意:优化可能是提示编译器内联移动函数,因此您仍然可以获得上述优势,而不会影响性能。

答案 1 :(得分:5)

决定分解函数的位置最重要的不一定是函数执行的程度。而不是确定你班级的API。

假设我们将Foo::do_stuff分为Foo::set_xFoo::twiddle_xFoo::set_y。单独进行这些操作是否有意义?如果我在没有先设置它的情况下旋转x,会发生什么不好的事吗?我可以在不致电set_y的情况下致电set_x吗?通过将它们分解为单独的方法,甚至是同一类中的私有方法,您暗示它们至少是潜在的单独操作。

如果情况并非如此,那么一定要将它们保存在一个功能中。

答案 2 :(得分:3)

  

我很清楚这很好   编程实践,以保持你的   功能/方法尽可能短

我不会使用上述标准将我的函数重构为较小的函数。以下是我使用的内容

  1. 将所有功能保持在同一级别 抽象
  2. 确保有     没有副作用(特殊情况     案例确保明确     记录他们)
  3. 确保某项功能不是一件事(SRP原则)。但你可以打破这一点来纪念1。
  4. 其他good practices for Method Design

    1. 不要让客户做任何事情 模块可以做
    2. 不要违反至少原则 惊讶
    3. 尽快报告错误快速报告错误 可能发生后
    4. 小心过载
    5. 使用适当的参数和返回类型
    6. 使用一致的参数排序 跨方法
    7. 避免长参数列表
    8. 避免需求的返回值 特殊处理

答案 3 :(得分:2)

在阅读了Clean Code: A Handbook of Agile Software Craftsmanship之后,我开始写这篇文章的几乎所有建议。不是为了具有简短的功能,而是为了提高可读性和可测试性,将它们保持在相同的抽象级别,让它们只做一件事等等。

我发现最有价值的是我发现自己编写的文档少得多,因为80%的函数不需要它。当函数只是它的名字所说的那样时,没有必要重述明显的。编写测试也变得更容易,因为每个测试方法可以设置更少并且执行更少的断言。当我重新审视过去六个月中编写这些目标的代码时,我可以更快地做出我想要的改变并继续前进。

答案 4 :(得分:0)

我认为在任何代码库中,可读性远远超过几个时钟周期,因为所有众所周知的原因,最重要的是可维护性,这是大多数代码花费时间的地方,因此大多数资金都是花在代码上。所以我有点躲避你的问题,说人们不关心它,因为它与其他[更公司]的担忧相比可以忽略不计。

虽然如果我们把其他问题放在一边,但是有明确的内联语句,更重要的是,编译器优化通常可以消除涉及普通函数调用的大部分开销。编译器是一个非常智能的优化机器,并且通常会比我们更智能地组织函数调用。