在2017年的cppcon视频中,我遇到了Klaus Iglberger的题为“Free Your Functions!”的演讲。 在这次演讲中,演讲者谈到了如何切换到免费功能 轻松测试私有方法的过程(见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
特有的实施细节。实际上,可以从代码中的任何地方调用它们......
所以我的问题是:为什么Iglberger先生的观点有效?
答案 0 :(得分:6)
这清楚地表明您存在设计缺陷。如果你有 您需要测试的私人功能,您必须向后弯曲 为了使它工作然后出了点问题。你错过了什么。 你的设计不起作用。
他的观点不仅仅是让私人职能免费。他并没有说:"获取所有私人功能并使其成为免费功能"。他说,需要测试的功能不应该是一个实现细节,因为如果你需要测试它,这表明功能是有用的。
请密切注意他对代码所做的转换:
初始代码:
class X
{
public:
void doSomething( ... ) {
...
resetValues();
...
}
...
private:
void resetValues() {
for( int& value : values_ )
value = 0;
}
std::vector<int> values_;
};
他从resetValues
中提取X
但使其在std::vector<T>
上运行,而不在X
上运行:
void resetValues( std::vector<int>& vec )
{
for( int& value : vec )
value = 0;
}
现在resetValues
是一种可以重复使用和测试的功能。因为它确实与X
无关,但是通过重置向量的所有值,使其成为自由函数而不是私有X
方法是有效的设计。
我喜欢Rann Lifshitz在评论中所说的话:
我认为更好的方法是去了解一些私人 事实上,函数是常用的函数函数
答案 1 :(得分:0)
我也观看了视频。但是,我有一些分歧。
1-您的方法是否需要访问字段?如果没有,它不属于该类。但如果确实如此,他们就需要这些领域。除非将它们作为函数参数传递,否则free函数无权访问这些字段。请考虑免费功能不应被视为公共功能。
2-并非一切都应该是自由功能。但是,如果没有必要,可以避免将所有内容都放在课堂上。
3-通常不应测试私人功能。但是如果你坚持,你可能会执行诸如无效的黑客攻击(这并不总是像评论中提到的那样工作):
#define class struct
#define private public
#define protected public
#include "library.h"
#undef class
#undef private
#undef protected
释放你的功能更整洁但不太可行。