3

在 2017 cppcon 视频中,我看到了 Klaus Iglberger 的演讲,题目是“释放你的函数! ”。在本次演讲中,演讲者谈到了切换到自由函数如何简化私有方法的测试过程(见 19:00)。这个想法是你将私有方法从类中拉出来(你使它成为一个自由函数)并且它变得可测试。

起初,我觉得这个想法很有趣,但后来我想得越多,我就越不明白这实际上应该如何工作。例如,假设我有以下(虚拟)类:

class SomeClass
{
public:
    SomeClass();
    ~SomeClass();

    void someTask();

private:

    void someComplexTask();
    void someOtherComplexTask();

};

void SomeClass::someTask()
{
    someComplexTask();
    someOtherComplexTask();
}

// private tasks implementations...

然后someComplexTask()someOtherComplexTask()是私有方法。这意味着它们是实现细节,即它们只能在内部SomeClass(或朋友)调用。在我看来,如果你让它们成为自由函数,是的,它们变得可测试,但它们不再是私有的,也不是特定于SomeClass. 事实上,它们可以从代码中的任何地方调用......

所以我的问题是:为什么伊格尔伯格先生的观点是有效的?

4

2 回答 2

7

这清楚地表明您存在设计缺陷。如果您有一个需要测试的私有函数并且您必须向后弯曲才能使其工作,那么就有问题了。你错过了一些东西。你的设计不行。

他的观点不仅仅是让私人功能免费。他并不是说:“获取你所有的私有函数并让它们成为自由函数”。他说需要测试的功能不应该是实现细节,因为如果您需要测试它,则表明该功能是有用的。

请密切注意他对代码所做的转换:

初始代码:

class X
{
public:
 void doSomething( ... ) {
    ...
    resetValues();
    ...
 }
 ...
private:
 void resetValues() {
     for( int& value : values_ )
        value = 0;
 }
 std::vector<int> values_;
};

resetValues退出,X 它使它在 a上运行std::vector<T>,而不是在X

void resetValues( std::vector<int>& vec )
{
 for( int& value : vec )
   value = 0;
}

现在resetValues是一个可以重用和测试的功能。因为它确实与 无关X,但是通过重置向量的所有值,使其成为自由函数而不是私有X方法是一种有效的设计。

我喜欢 Rann Lifshitz 在他的评论中所说的:

我认为更好的方法是了解一些私有函数实际上是常见的效用函数

于 2018-03-28T01:48:20.537 回答
0

我也看过视频。但是,我有一些不同意见。

1-您的方法是否需要访问字段?如果不是,则它不属于该类。但如果是这样,他们需要这些字段。除非您将它们作为函数参数传递,否则自由函数无法访问这些字段。请考虑免费功能不应被视为公共功能。

2-并非所有内容都应该是免费功能。但最好避免在不必要时将所有内容都放在课堂上。

3-私有功能通常不应该被测试。但是,如果您坚持,您也许可以执行无效的黑客攻击(这并不总是像评论中提到的那样有效):

#define class struct
#define private public
#define protected public

#include "library.h"

#undef class
#undef private
#undef protected

释放你的函数更简洁但不是更可行。

于 2018-03-28T01:45:13.207 回答