Что такое принцип инверсии зависимостей (Dependency Inversion Principle, DIP)?

«Что такое принцип инверсии зависимостей (Dependency Inversion Principle, DIP)?» — вопрос из категории ООП, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Принцип инверсии зависимостей (DIP) — пятый принцип SOLID. Он декларирует:

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

Цель — уменьшить связанность между компонентами, сделав систему более гибкой, расширяемой и удобной для тестирования.

Пример нарушения DIP в C++:

// Модуль нижнего уровня (деталь)
class SqlDatabase {
public:
    void saveData(const std::string& data) { /* ... */ }
};

// Модуль верхнего уровня жёстко зависит от детали
class ReportService {
    SqlDatabase db; // Прямая зависимость от конкретного класса
public:
    void generateReport() {
        // ... логика отчёта
        db.saveData(reportData);
    }
};

Здесь ReportService тесно связан с SqlDatabase. Замена базы данных потребует изменений в ReportService.

Пример с применением DIP:

// Абстракция (интерфейс)
class IDataStorage {
public:
    virtual ~IDataStorage() = default;
    virtual void save(const std::string& data) = 0;
};

// Модуль нижнего уровня зависит от абстракции
class SqlDatabase : public IDataStorage {
public:
    void save(const std::string& data) override { /* ... */ }
};

class FileStorage : public IDataStorage {
public:
    void save(const std::string& data) override { /* ... */ }
};

// Модуль верхнего уровня также зависит от абстракции
class ReportService {
    IDataStorage& storage; // Зависимость от интерфейса
public:
    ReportService(IDataStorage& s) : storage(s) {} // Внедрение зависимости
    void generateReport() {
        // ... логика отчёта
        storage.save(reportData);
    }
};

Теперь ReportService не знает о деталях хранения данных. Мы можем легко подменить реализацию IDataStorage (для тестирования, смены БД и т.д.), не меняя код сервиса.

Видео-ответы