编码时我总是遇到这样的问题。
有一个名为" INetworkReader"的界面,如下所示:
struct INetworkReader
{
virtual void readFile(const std::string& url) = 0;
...
};
现在,我想扩展readFile()函数,readFile()函数需要设置超时或其他东西以实现更多控件,所以现在我有两个解决方案。
解决方案1(添加默认参数):
struct INetworkReader
{
virtual void readFile(const std::string& url, int timeout = 0) = 0;
...
};
解决方案2(添加另一个功能):
struct INetworkReader
{
virtual void readFile(const std::string& url) = 0;
virtual void readFileTimeout(const std::string& url,int timeout) = 0;
...
};
我更喜欢解决方案1,因为它的参数清楚地描述了它的动作,我认为唯一的缺点就是增加了参数的数量。
那么,如你所见,哪个看起来更好?为什么呢?
我发现了另一个可能更复杂的案例,请查看以下代码。
struct IComputer
{
virtual bool addMouse(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse ) = 0;
}
现在想要添加一个参数来判断它是否添加到USB端口,这些仍然有两个解决方案。
解决方案1(添加默认参数):
struct IComputer
{
virtual bool addMouse(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse, /* in */ bool USBPort = true ) = 0;
}
解决方案2(添加另一个功能):
struct IComputer
{
virtual bool addMouse(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse ) = 0;
virtual bool addMouseNotUSB(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse ) = 0;
}
这次我更喜欢第二个解决方案,因为第一个解决方案已经打破了输入输出参数的序列。
那么,两个案例,四个解决方案,哪一个更好?为什么呢?答案 0 :(得分:1)
IMO我更喜欢解决方案2(只要它需要一个超时参数)。如果您是第一次面对代码,则可以快速了解表达式readFileTimeout(url, 1000)
中的“1000”,而不是readFile(url, 1000)
。在第二个表达式中,人们可以认为代码正在读取1000个字节,例如。
在第二种情况下,我也更喜欢使用不同的函数名,但由于我们传递了一个布尔值,我会使用函数名来从中推导出布尔值:
addMouse(const std::string& mouseID, IMouse** ppMouse) //For non-USB mice
addUSBMouse(const std::string& mouseID, IMouse** ppMouse) //For USB mice
是否使用反逻辑(即创建addNonUSBMouse
而不是addUSBMouse
)的决定是任意的,取决于您的代码可能会运行的情况。如果在大多数情况下鼠标不是USB,请使用我的建议。否则使用逆逻辑版本。
我的引理是:尝试以不必阅读原型的方式命名函数。
答案 1 :(得分:1)
另一个选择是使用类型强制在调用代码中表达:
struct INetworkReader
{
virtual void readFile(const std::string& url, Timeout timeout = Timeout::Infinite) = 0;
...
};
调用代码可能是:
p->readFile(url, Timeout{200, Timeout::ms});
表示Timeout
为0有点模棱两可:它可能意味着对数据进行非阻塞检查,或者可能无限期阻止,因此值为Infinite
或Never
更清楚。
使用C ++ 14,您可以从std::chrono::duration
创建一个明确的Timeout
构造函数,例如200ms
。
对于鼠标示例:
enum Connection { USB, NonUSB };
virtual std::pair<bool, IMouse*> addMouse(const std::string& mouseID,
Connection connection = USB ) = 0;
请注意,对于输入/输出参数问题,我已经返回了所有输出而不是IMouse**
?您可以返回tuple
,pair
或自定义struct
。
答案 2 :(得分:0)
溶液1是优选的。对于包含两个参数的函数来说,它绝对可以。当参数太多时,只需考虑其他解决方案(例如构造函数的参数太多的Builder模式)。