Когда нужно принимать интерфейс?

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

Ответ

Принимать интерфейс в качестве зависимости следует для достижения слабой связанности (loose coupling) и соблюдения принципа инверсии зависимостей (DIP). Это позволяет:

  • Абстрагироваться от конкретной реализации. Клиентский код зависит только от контракта (методов интерфейса), а не от деталей реализации.
  • Упростить тестирование. Зависимость легко подменить mock- или stub-объектом в юнит-тестах.
  • Повысить гибкость архитектуры. Реализации можно менять или добавлять новые, не затрагивая существующий клиентский код.

Пример на C#:

// Контракт
public interface ILogger
{
    void Log(string message);
}

// Конкретная реализация №1
public class FileLogger : ILogger
{
    public void Log(string message) => File.AppendAllText("app.log", message);
}

// Конкретная реализация №2
public class ConsoleLogger : ILogger
{
    public void Log(string message) => Console.WriteLine($"[LOG] {message}");
}

// Сервис, зависящий от абстракции (интерфейса)
public class OrderService
{
    private readonly ILogger _logger;
    // Внедрение зависимости через конструктор
    public OrderService(ILogger logger)
    {
        _logger = logger;
    }

    public void PlaceOrder(Order order)
    {
        // Логика размещения заказа...
        _logger.Log($"Order {order.Id} placed.");
    }
}
// Использование: можно легко подменить реализацию логгера.
var serviceWithFileLog = new OrderService(new FileLogger());
var serviceWithConsoleLog = new OrderService(new ConsoleLogger());