什么时候违反单一责任原则?

Sil*_*lex 1 c++ coding-style single-responsibility-principle design-principles

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

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

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();
}
Run Code Online (Sandbox Code Playgroud)

这看起来很自然,但看起来 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);
Run Code Online (Sandbox Code Playgroud)

这里的东西在职责方面被整齐地分开,但现在它看起来非常像具有愚蠢结构和函数的 C...这引出了一个问题:为什么我们首先需要 OOP。

您如何在便利性和建议零售价之间取得平衡?

[编辑]

@stjin 的想法被@John Zwinck 显示为答案

Joh*_*nck 5

我会这样写你的例子:

class Session
{
public:
  Session(string url, string user, string password);
};

class Camera
{
public:
  Camera(Session);

  image take_snapshot();
  bool reboot();
};
Run Code Online (Sandbox Code Playgroud)

这里的主要思想是将身份验证和会话/端点定义(可能还有连接)与相机控件分开。Camera 类现在更接近于真实相机的模型:它有一个电源按钮和一个快门按钮之类的东西。相机的虚拟化在其他地方,单独进行。如果有人想为不同的相机建立 USB 会话等,这也使得该做什么变得更加明显。

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

顺便说一句,自由函数没有什么问题。OOP 被高估了,我们都知道这一点,如果免费函数在您的用例中工作,您不应该感到有必要道歉。哑结构可能比无意义的 getter 和 setter 更好——特别是如果您不构建具有 ABI 兼容性要求的可重用库。