Должен ли клиентский код зависеть от деталей реализации?

«Должен ли клиентский код зависеть от деталей реализации?» — вопрос из категории Архитектура, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, клиентский код должен зависеть от абстракций, а не от деталей. Это ключевой принцип Dependency Inversion (D) из SOLID.

Проблема зависимости от деталей:

  • Жесткая связь: Усложняет замену реализации.
  • Сложное тестирование: Затрудняет использование mock-объектов.
  • Распространение изменений: Изменение в деталях требует правок во многих клиентах.

Пример нарушения (плохо):

class PaymentProcessor {
    // Прямая зависимость от конкретного платежного шлюза
    private StripeGateway gateway = new StripeGateway();
    public void process(Payment p) {
        gateway.charge(p); // Деталь реализации
    }
}

Решение через абстракцию (хорошо):

// 1. Абстракция (интерфейс)
interface PaymentGateway {
    void charge(Payment p);
}

// 2. Конкретная реализация
class StripeGateway implements PaymentGateway { /*...*/ }
class PayPalGateway implements PaymentGateway { /*...*/ }

// 3. Клиент зависит от интерфейса
class PaymentProcessor {
    private PaymentGateway gateway; // Абстракция
    public PaymentProcessor(PaymentGateway gateway) { // Внедрение зависимости
        this.gateway = gateway;
    }
    public void process(Payment p) {
        gateway.charge(p); // Работает с любой реализацией
    }
}

Итог: Зависимость от абстракций повышает гибкость, тестируемость и соответствие принципу открытости/закрытости.