Что означает буква D в принципах SOLID?

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

Ответ

Буква D в SOLID означает Принцип инверсии зависимостей (Dependency Inversion Principle, DIP).

Его суть в том, что:

  1. Модули верхнего уровня (например, бизнес-логика) не должны зависеть от модулей нижнего уровня (например, конкретная база данных или внешний сервис). Оба должны зависеть от абстракций (интерфейсов).
  2. Абстракции не должны зависеть от деталей. Детали (конкретные реализации) должны зависеть от абстракций.

Почему это важно в Node.js? Это делает код гибким, тестируемым и упрощает замену одной реализации на другую.

Пример на TypeScript с использованием интерфейса для слоя работы с данными:

// Абстракция (интерфейс), от которой зависят и сервис, и репозиторий
interface IUserRepository {
  findById(id: string): Promise<User | null>;
  save(user: User): Promise<void>;
}

// Конкретная реализация для MongoDB (деталь)
class MongoUserRepository implements IUserRepository {
  async findById(id: string): Promise<User | null> {
    // ... код работы с Mongoose
  }
  async save(user: User): Promise<void> { /* ... */ }
}

// Сервис (модуль верхнего уровня) зависит от абстракции IUserRepository
class UserService {
  constructor(private userRepository: IUserRepository) {}

  async getUser(id: string) {
    return this.userRepository.findById(id);
  }
}

// Внедряем конкретную реализацию через зависимость
const userService = new UserService(new MongoUserRepository());

Таким образом, если завтра нужно будет перейти на PostgreSQL, мы просто создадим класс PostgresUserRepository, реализующий тот же интерфейс IUserRepository, и передадим его в UserService, не меняя сам сервис.