TODO: отвалидировать – текст собран автоматически из материалов курса на Google Drive, проверьте формулировки и код.
Проблема модификации системы наиболее актуальна в условиях динамически изменяющихся требований.
Зачастую удаётся заранее выделить точки неустойчивости – места, которые будут меняться чаще остальных. Тогда эти точки определяют в качестве интерфейсов, и изменение прячется за границей, не расходясь по всей системе.
// Точка неустойчивости: способ доставки уведомлений будет меняться
public interface INotifier
{
void Notify(User user, string message);
}
public class EmailNotifier : INotifier { public void Notify(User u, string m) { } }
public class SmsNotifier : INotifier { public void Notify(User u, string m) { } }
// Точка неустойчивости: способ доставки уведомлений будет меняться
class INotifier {
public:
virtual void Notify(const User& user, const std::string& message) = 0;
virtual ~INotifier() = default;
};
class EmailNotifier : public INotifier {
public:
void Notify(const User& user, const std::string& message) override {}
};
class SmsNotifier : public INotifier {
public:
void Notify(const User& user, const std::string& message) override {}
};
// Точка неустойчивости: способ доставки уведомлений будет меняться
type Notifier interface {
Notify(user User, message string) error
}
type EmailNotifier struct{}
func (EmailNotifier) Notify(user User, message string) error { return nil }
type SMSNotifier struct{}
func (SMSNotifier) Notify(user User, message string) error { return nil }
# Точка неустойчивости: способ доставки уведомлений будет меняться
from typing import Protocol
class Notifier(Protocol):
def notify(self, user: User, message: str) -> None: ...
class EmailNotifier:
def notify(self, user: User, message: str) -> None:
pass
class SmsNotifier:
def notify(self, user: User, message: str) -> None:
pass
// Точка неустойчивости: способ доставки уведомлений будет меняться
interface Notifier {
notify(user: User, message: string): void;
}
class EmailNotifier implements Notifier {
notify(user: User, message: string): void {}
}
class SmsNotifier implements Notifier {
notify(user: User, message: string): void {}
}
// Точка неустойчивости: способ доставки уведомлений будет меняться
public interface Notifier {
void notify(User user, String message);
}
public class EmailNotifier implements Notifier {
public void notify(User user, String message) { }
}
public class SmsNotifier implements Notifier {
public void notify(User user, String message) { }
}
// Точка неустойчивости: способ доставки уведомлений будет меняться
fun interface Notifier {
fun notify(user: User, message: String)
}
class EmailNotifier : Notifier {
override fun notify(user: User, message: String) = Unit
}
class SmsNotifier : Notifier {
override fun notify(user: User, message: String) = Unit
}
Главная сложность
Принцип требует угадать, что именно будет меняться. Защита от изменений, которых не произошло, – это лишние интерфейсы и лишние слои, за которые платят все читатели кода.
Практическое правило: защищайте то, что уже менялось хотя бы раз, а не то, что теоретически может измениться.