1

注意:对于这个问题,我主要指的是 C++,但这可能适用于其他语言。

注意:请假设没有递归。

人们经常说(如果你有一个非常大的函数)将一个函数“分解”成几个更小的函数,但这是合乎逻辑的吗?如果我知道我永远不会使用其中一个较小的函数怎么办,那只是浪费:内存、性能,而且您在阅读代码时可能不得不更多地跳过代码。另外,如果您只使用一次(假设很大)函数,您是否应该将函数体插入到将被调用的位置(出于与上次相同的原因,即:内存、性能,并且您可能有在阅读代码时更多地跳转代码)?所以...做一个功能还是不做一个功能,这是个问题。

全部 *编辑*

我仍在浏览所有答案,但是从我到目前为止所读到的内容中,我已经形成了一个假设。

在开发期间将其拆分功能是否正确,但在部署之前执行我在问题中的建议,以及在开发中使用一次的功能,但在部署之前插入主体?

4

3 回答 3

1

这真的取决于上下文。

当我们说函数的大小时,我们实际上是指函数内部线条的语义距离。我们更喜欢一个函数只做一件事。如果你的函数只做一件事,并且里面的语义距离很小,那么有大函数是可以的。

但是,让一个函数做很多事情并不是一个好习惯,最好将这些函数重构为几个较小的,命名好,代码放置好,这样代码的用户就不需要跳转大约。

于 2013-01-19T01:27:06.220 回答
1

不要太担心性能和内存。您的编译器应该为您处理大部分内容,尤其是对于非常薄的函数。

我的目标通常是确保可以在读者的记忆中完全替换给定的函数调用——开发人员可以纯粹地处理抽象。拿着这个:

// Imagine here that these are real variable/function names as written by a
// lazy coder. I have seen code like this in the wild.
void someFunc(int arg1, int arg2) {
  int val3 = doFirstPart(arg1, field1);
  int val4 = doSecondPart(arg2, val3);
  queue.push(val4);
}

doFirstPart 和 doSecondPart 的重构给你带来的收益很少,而且可能会让事情变得更难理解。但是,这里的问题不是方法提取:问题是糟糕的命名和抽象!您将不得不阅读doFirstPartdoSecondPart或者整个功能的重点都丢失了。

考虑一下,而不是:

void pushLatestRateAndValue(int rate, int value) {
  int rateIndex = calculateRateIndex(rate, latestRateTable);
  int valueIndex = caludateValueIndex(rateIndex, value);
  queue.push(valueIndex);
}

在这个人为的例子中,你不必阅读calculateRateIndex,或者calculateValueIndex除非你真的想深入挖掘——你只要阅读就知道它做了什么。

除此之外,这可能是个人风格的问题。我知道有些程序员喜欢将每个业务“声明”提取到不同的函数中,但我发现这有点难以阅读。我个人的偏好是寻找机会从任何长于一个“屏幕”(约 25 行)的函数中提取一个函数,这具有使整个函数一次可见的优点,而且因为 25 行发生在我的个人心理上短期记忆的限制和暂时的理解。

于 2013-01-19T01:28:13.687 回答
1

有很多很好的论据可以证明例程的长度不要超过一页纸的大致长度。大多数人并不总是想到的是——除非你部署调试符号,大多数人不这样做——从现场传来的堆栈跟踪更容易分析并变成关于原因的假设它所指的例程比错误发生在你从未有机会拆分的方法的 2,000 行鲸鱼中的某个地方时要小。

于 2013-01-19T01:40:03.670 回答