何时违反单一责任原则

When to violate the single responsibility principle?

本文关键字:原则 责任 单一 何时违      更新时间:2023-10-16

如何决定何时以及如何违反单一责任原则?

例如,假设我有一个具有以下接口的网络相机(为了简单起见,接口保持愚蠢和"错误"):

class Camera
{
string user();
void set_user(string user);
string password();
void set_password(string password);
string url();
void set_url(string url);
image take_snapshot();
bool reboot();
}

这看起来很自然,但Camera类似乎有3个职责:存储元数据、拍摄快照、重新启动。按照SRP,你可以这样写:

class Camera
{
string user();
void set_user(string user);
string password();
void set_password(string password);
string url();
void set_url(string url);
}
image take_snapshot(camera c);
bool reboot_camera(camera c);

这里的东西在响应性方面被巧妙地分开了,但现在它看起来很像C,有着愚蠢的结构和函数。。。这就引出了我们为什么首先需要OOP的问题。

您如何在便利性和SRP之间取得平衡?

[编辑]

@stjin的想法被@John Zwinck 展示为一个答案

我会这样写你的例子:

class Session
{
public:
Session(string url, string user, string password);
};
class Camera
{
public:
Camera(Session);
image take_snapshot();
bool reboot();
};

这里的主要思想是将身份验证和会话/端点定义(也许还有连接)与相机控件分离。Camera类现在更像是一台真正的相机:它有一个电源按钮和一个快门按钮。相机的虚拟化本身就在其他地方。这也使得如果有人想为不同的相机等进行USB会话,该怎么办变得更加明显。

这里的次要思想是,对象从一开始就以有效状态创建。例如,在没有密码的情况下,无法配置相机,因此在没有凭据的情况下调用take_snapshot()是不可能的。当然,凭据可能无效,但可以通过某个构造函数中可能调用的方法进行检查。

顺便说一句,自由函数没有错。OOP被高估了,我们都知道,如果免费函数在你的用例中有效,你不应该觉得有任何道歉的必要。愚蠢的结构可能比毫无意义的getter和setter更好——尤其是如果你没有构建一个具有ABI兼容性要求的可重用库。