使用较小的函数来分解长方法 - 正确的风格/如何声明
Using smaller functions to break up long methods - correct style / how to declare
我的 类 中有一个冗长且令人困惑的静态方法。它是完整的或错误检查代码,结果变成了不可读的意大利面条!它看起来像这样:
void myMethod(int foo, int bar)
{
int y = functionCall(foo);
if (!y)
{
int x = functionCall(bar);
if (!x)
{
// lots of code with further nested ifs for error checking
// it all starts to get a bit confusing
}
else
{
// error handling
}
}
else
{
// error handling
}
}
为了代码可读性和模块化程度更高(让我更容易测试/维护等),我想把它分解成一些更小的函数。这与代码重用无关,因为函数只会从一个地方调用 - 它纯粹是关于可读性,并使 100 行复杂代码更容易被人类理解。
所以我的问题是这样的。
如果我这样做,我是否会因为进行不必要的调用而降低效率,从而给处理器带来额外的工作?
如果我制作这些较小的函数,我是否应该将它们声明为内联以帮助链接器意识到它们只被这个函数使用并且应该就地分解?
链接器能否自行管理此类优化?
最后,如果我要内联声明它,正确的方法是什么?
是否应该将内联函数声明放在header文件中,将代码body放在.cpp文件中?
i.e.
in MyClass.hpp :
inline static int myMethodPart1();
in MyClass.cpp
int MyClass::myMethodPart1()
{ /* body */ }
或者我不应该在 header 或 ..... 中声明它?
关于如何组织和划分代码,我想你需要有良好的判断力。如果您觉得这是一个大到 post 的问题,那么解决它可能是值得的。也就是说,我将尝试单独解决您的 post 的组件。
函数调用的成本。函数调用非常便宜。该系统本质上只是取消引用一个指针,它就在那里。类似的情况已经发生在循环、条件和其他形式的分支中。声明:
While( x != 0 )
{
Do stuff;
}
将在低级别编译以有效地“做事”;作为重复调用的单独函数。因此,将函数拆分为多个函数的成本很低,如果使用智能编译器干净地完成,可能 non-existent.
关于内联。 正如我在评论中解释的那样,inline
关键字并不(完全)代表您认为的含义和暗示的含义。关于实际内联函数,编译器倾向于忽略 inline
,最多将其作为建议。 inline
所做的是防止函数的多个定义成为错误。如果您在 header 中定义一个函数,这是很重要的行为,因为该函数定义将被编译到每个 cpp 的 object 文件中。如果未声明 [=12=],将这些 object 链接到可执行文件中会产生多重定义错误。一些编译器隐式内联以这种方式定义的函数,但你永远不应该依赖 compiler-specific 行为。
实际上,内联函数在一定程度上取决于编译器的优势。我已经看到它说,虽然我现在找不到在哪里,但在 class 声明中(在 header 中)定义一个函数是对编译器内联的一个相当强烈的点头。
也就是说,正如我之前提到的,内联并不是一个特别重要的问题。调用函数的成本低得离谱,真正应该关注的唯一领域是经常调用的函数——比如 getter 和 setter 函数。
如何使用内联。已经建立inline
不内联,通常,你关于使用它的问题是主要如上所述。如果在 class 声明中定义函数,请使用 inline
关键字以避免可能的链接器错误。否则,据我所知,对于大多数现代编译器来说,它基本上是一个无意义的关键字。
将拆分单个函数形成的函数放在哪里。这是一个非常基于意见的问题,但我认为有两个选项似乎最好:
首先,您可以将其设为 class 的受保护成员。如果这样做,您可能应该包括一个符号点头,表明这不是 general-purpose 函数 - 名称中的前导下划线通常是 "do not touch."
的符号
或者,您可以在 .cpp 文件中定义额外的函数,而不是在 class 本身中。例如 [MyClass.cpp]:
void functionA()
{
stuff;
}
void functionB()
{
stuff;
}
void MyClass::myFunction()
{
functionA();
functionB();
}
这完全防止了在这个 cpp 文件之外调用这些函数。它还会阻止来自 child classes 的调用,这可能是也可能不是理想的行为。请自行决定将它们放在哪里。
最后一点。 小心划分复杂函数的方式,否则最终可能会得到比单个函数更糟糕的结果。将东西移到别处可能只会掩盖实际逻辑混乱的事实。我个人发现遵循单个分支函数比调用其他函数要简单得多。如果出于潜在 non-obvious 原因在函数外部进行调用,则阅读起来会更加困难,尤其是对于不熟悉代码的人。
考虑如何重新组织代码以使其更简单(如果可能)并将其保留在一个函数中 - 或者以可重用的方式划分代码可能会有所帮助。
我的 类 中有一个冗长且令人困惑的静态方法。它是完整的或错误检查代码,结果变成了不可读的意大利面条!它看起来像这样:
void myMethod(int foo, int bar)
{
int y = functionCall(foo);
if (!y)
{
int x = functionCall(bar);
if (!x)
{
// lots of code with further nested ifs for error checking
// it all starts to get a bit confusing
}
else
{
// error handling
}
}
else
{
// error handling
}
}
为了代码可读性和模块化程度更高(让我更容易测试/维护等),我想把它分解成一些更小的函数。这与代码重用无关,因为函数只会从一个地方调用 - 它纯粹是关于可读性,并使 100 行复杂代码更容易被人类理解。
所以我的问题是这样的。
如果我这样做,我是否会因为进行不必要的调用而降低效率,从而给处理器带来额外的工作?
如果我制作这些较小的函数,我是否应该将它们声明为内联以帮助链接器意识到它们只被这个函数使用并且应该就地分解?
链接器能否自行管理此类优化?
最后,如果我要内联声明它,正确的方法是什么?
是否应该将内联函数声明放在header文件中,将代码body放在.cpp文件中?
i.e.
in MyClass.hpp :
inline static int myMethodPart1();
in MyClass.cpp
int MyClass::myMethodPart1()
{ /* body */ }
或者我不应该在 header 或 ..... 中声明它?
关于如何组织和划分代码,我想你需要有良好的判断力。如果您觉得这是一个大到 post 的问题,那么解决它可能是值得的。也就是说,我将尝试单独解决您的 post 的组件。
函数调用的成本。函数调用非常便宜。该系统本质上只是取消引用一个指针,它就在那里。类似的情况已经发生在循环、条件和其他形式的分支中。声明:
While( x != 0 )
{
Do stuff;
}
将在低级别编译以有效地“做事”;作为重复调用的单独函数。因此,将函数拆分为多个函数的成本很低,如果使用智能编译器干净地完成,可能 non-existent.
关于内联。 正如我在评论中解释的那样,inline
关键字并不(完全)代表您认为的含义和暗示的含义。关于实际内联函数,编译器倾向于忽略 inline
,最多将其作为建议。 inline
所做的是防止函数的多个定义成为错误。如果您在 header 中定义一个函数,这是很重要的行为,因为该函数定义将被编译到每个 cpp 的 object 文件中。如果未声明 [=12=],将这些 object 链接到可执行文件中会产生多重定义错误。一些编译器隐式内联以这种方式定义的函数,但你永远不应该依赖 compiler-specific 行为。
实际上,内联函数在一定程度上取决于编译器的优势。我已经看到它说,虽然我现在找不到在哪里,但在 class 声明中(在 header 中)定义一个函数是对编译器内联的一个相当强烈的点头。
也就是说,正如我之前提到的,内联并不是一个特别重要的问题。调用函数的成本低得离谱,真正应该关注的唯一领域是经常调用的函数——比如 getter 和 setter 函数。
如何使用内联。已经建立inline
不内联,通常,你关于使用它的问题是主要如上所述。如果在 class 声明中定义函数,请使用 inline
关键字以避免可能的链接器错误。否则,据我所知,对于大多数现代编译器来说,它基本上是一个无意义的关键字。
将拆分单个函数形成的函数放在哪里。这是一个非常基于意见的问题,但我认为有两个选项似乎最好:
首先,您可以将其设为 class 的受保护成员。如果这样做,您可能应该包括一个符号点头,表明这不是 general-purpose 函数 - 名称中的前导下划线通常是 "do not touch."
的符号或者,您可以在 .cpp 文件中定义额外的函数,而不是在 class 本身中。例如 [MyClass.cpp]:
void functionA()
{
stuff;
}
void functionB()
{
stuff;
}
void MyClass::myFunction()
{
functionA();
functionB();
}
这完全防止了在这个 cpp 文件之外调用这些函数。它还会阻止来自 child classes 的调用,这可能是也可能不是理想的行为。请自行决定将它们放在哪里。
最后一点。 小心划分复杂函数的方式,否则最终可能会得到比单个函数更糟糕的结果。将东西移到别处可能只会掩盖实际逻辑混乱的事实。我个人发现遵循单个分支函数比调用其他函数要简单得多。如果出于潜在 non-obvious 原因在函数外部进行调用,则阅读起来会更加困难,尤其是对于不熟悉代码的人。
考虑如何重新组织代码以使其更简单(如果可能)并将其保留在一个函数中 - 或者以可重用的方式划分代码可能会有所帮助。