Что такое dependency injection

«Что такое dependency injection» — вопрос из категории Паттерны, который задают на 59% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Dependency Injection (DI, внедрение зависимостей) — это паттерн, при котором зависимости объекта (сервисы, репозитории, конфигурации) предоставляются ему извне, обычно через конструктор, метод или свойство, а не создаются внутри самого объекта.

Проблема без DI (жесткая связь):

class UserService {
  constructor() {
    // Зависимость создается внутри класса, что усложняет тестирование и замену.
    this.userRepository = new PostgreSQLUserRepository();
  }
  async getUser(id) {
    return this.userRepository.findById(id);
  }
}

Решение с DI (гибкая связь):

class UserService {
  // Зависимость внедряется извне.
  constructor(userRepository) {
    this.userRepository = userRepository;
  }
  async getUser(id) {
    return this.userRepository.findById(id);
  }
}

// Где-то в точке входа в приложение (например, index.js или контейнере DI) собираем объекты:
const userRepository = new PostgreSQLUserRepository();
const userService = new UserService(userRepository);

// Теперь для тестов легко подменить репозиторий на мок:
const mockRepository = { findById: jest.fn(() => ({ id: 1, name: 'Test' })) };
const testUserService = new UserService(mockRepository);

В Node.js-экосистеме DI часто используется с:

  • Фреймворками: NestJS имеет мощную встроенную систему DI на основе декораторов.
  • Библиотеками: InversifyJS, Awilix, TSyringe.
  • Ручной инъекцией: Простая передача зависимостей через конструкторы, что часто достаточно для небольших проектов.

Основные преимущества: повышение тестируемости, уменьшение связанности кода, упрощение рефакторинга и конфигурации.