Ответ
Ввожу абстракцию в первую очередь для того, чтобы управлять зависимостями и снижать связность между модулями. Это ключевой принцип для создания тестируемого и поддерживаемого кода.
Конкретные случаи из практики:
- Работа с внешними зависимостями: Все взаимодействия с базами данных, API, файловыми системами или сторонними сервисами (платежи, email, смс) я абстрагирую за интерфейсом. Это позволяет легко подменять реальную реализацию моком в unit-тестах.
- Наличие или ожидание нескольких реализаций: Если есть алгоритм сортировки, который может выполняться по-разному (QuickSort, MergeSort), или способ отправки уведомлений (Email, SMS, Push) — это прямой сигнал к введению абстракции.
- Следование принципу инверсии зависимостей (DIP): Модули верхнего уровня (бизнес-логика) не должны зависеть от модулей нижнего уровня (инфраструктура). Оба должны зависеть от абстракций.
Пример на C#:
// Абстракция для службы отправки уведомлений
public interface INotificationService
{
Task SendAsync(string recipient, string message);
}
// Конкретная реализация для Email
public class EmailNotificationService : INotificationService
{
public async Task SendAsync(string recipient, string message)
{
// Логика отправки email через SMTP или SendGrid API
await _smtpClient.SendMailAsync(...);
}
}
// Класс бизнес-логики, зависящий от абстракции
public class OrderProcessor
{
private readonly INotificationService _notifier;
// Внедрение зависимости через конструктор
public OrderProcessor(INotificationService notifier)
{
_notifier = notifier;
}
public async Task ProcessOrder(Order order)
{
// ... логика обработки заказа
await _notifier.SendAsync(order.CustomerEmail, "Your order is confirmed!");
}
}
// В тестах используем заглушку
public class MockNotificationService : INotificationService
{
public List<string> SentMessages { get; } = new();
public Task SendAsync(string recipient, string message)
{
SentMessages.Add($"To: {recipient}, Msg: {message}");
return Task.CompletedTask;
}
}
Важное правило: Не создаю абстракцию «на будущее», если нет хотя бы одной конкретной причины или уже существующей второй реализации. Преждевременная абстракция так же вредна, как и ее отсутствие.