Как вы решаете, когда и как нарушать принцип единой ответственности?
Например, допустим, у меня есть сетевая камера со следующим интерфейсом (интерфейс для простоты оставался глупым и «неправильным»):
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 с тупыми структурами и функциями … что вызывает вопрос о том, зачем нам в первую очередь нужен ООП.
Как вы балансируете между удобством и 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 () без учетных данных просто невозможен. Конечно, учетные данные могут быть недействительными, но это может быть проверено некоторым методом, который может быть вызван в одном из конструкторов.
Кроме того, нет ничего плохого в свободных функциях. ООП переоценена, мы все это знаем, и вам не нужно извиняться, если в вашем случае работают бесплатные функции. Глупые структуры могут быть лучше, чем бессмысленные методы получения и установки, особенно если вы не создаете повторно используемую библиотеку, которая имеет требования совместимости ABI.
Других решений пока нет …