TGViewer
Flutter Friendly Flutter Friendly @flutterfriendly · 995 subscribers
Post #301 838
❄️Привет, с вами Катя, Flutter Dev Friflex

В предыдущем посте я рассказывала о принципе разделения интерфейса (I). Сегодня разбираем последнюю букву — D (Dependency Inversion Principle), принцип инверсии зависимостей.

Что такое Dependency Inversion Principle?
Принцип инверсии зависимостей говорит о двух вещах:
✔️высокоуровневые модули не должны зависеть от низкоуровневых — и те, и другие должны зависеть от абстракций
✔️абстракции не должны зависеть от деталей, детали должны зависеть от абстракций.
По-простому: «верх» приложения (экран, бизнес-логика) не должен быть привязан к конкретным реализациям «низа» (HTTP‑клиент, база данных, SharedPreferences и другим), он должен зависеть только от интерфейсов.

Почему это важно?
Когда высокоуровневый код напрямую знает о конкретных классах нижнего уровня, это приводит к проблемам:

◾️Любое изменение реализации «внизу» (REST → gRPC, другая БД, кэш) требует правок в бизнес-логике
◾️Код сложно тестировать — приходится тянуть реальные репозитории/сети вместо заглушек
◾️Система становится хрупкой: одна деталь «внизу» ломает много кода «наверху»
◾️Нарушаются другие принципы SOLID — растет связанность, падает переиспользуемость.

Инверсия зависимостей как раз про то, чтобы «перевернуть» направление зависимости: не высокоуровневый модуль зависит от деталей, а детали зависят от контракта, который описывает высокоуровневый модуль.

❌Нарушение принципа
Рассмотрим типичный пример с авторизацией:

class AuthRepository {
  Future<void> login(String email, String password) async {
    // Здесь конкретная реализация:
    // HTTP-запрос, парсинг ответа, сохранение токена и т.д.
  }
}

class LoginViewModel {
  Future<void> login(String email, String password) async {
    final repo = AuthRepository(); // Жёсткая зависимость
    await repo.login(email, password);
  }
}


Проблемы:
✖️LoginViewModel сам создает AuthRepository и жестко на него завязан
✖️Нельзя легко подменить репозиторий в тестах (например, на фейковый, который не ходит в сеть)
✖️Любое изменение механизма авторизации требует лезть в LoginViewModel
✖️Высокоуровневый модуль (view model) зависит от конкретной детали (репозитория), а не от абстракции

✅Правильное применение принципа
Введем абстракцию и будем передавать зависимость извне (через конструктор):

// Абстракция (контракт), от которой зависит верхний уровень
abstract class IAuthRepository {
  Future<void> login(String email, String password);
}

// Низкоуровневая реализация для реального API
class NetworkAuthRepository implements IAuthRepository {
  @override
  Future<void> login(String email, String password) async {
    // HTTP, обработка ошибок, сохранение токена и т.д.
  }
}

// Другая реализация, например, фейковая для тестов
class FakeAuthRepository implements IAuthRepository {
  @override
  Future<void> login(String email, String password) async {
    // Ничего не делает или имитирует успешный логин
  }
}

// Высокоуровневый модуль зависит только от интерфейса
class LoginViewModel {
  final IAuthRepository _authRepository;

  LoginViewModel(this._authRepository);

  Future<void> login(String email, String password) async {
    await _authRepository.login(email, password);
  }
}


Теперь:
✔️LoginViewModel не знает, как именно реализован репозиторий — он видит только интерфейс
✔️В проде можно передать NetworkAuthRepository, в тестах — FakeAuthRepository
✔️Изменения в реализации репозитория не требуют правок в бизнес-логике
✔️Мы перевернули зависимость: конкретные реализации зависят от абстракции IAuthRepository, а не наоборот

Если вы видите в коде new/() внутри бизнес‑логики или ViewModel, создающий конкретные репозитории, сервисы и клиенты, — это хороший сигнал задуматься: не пора ли ввести интерфейс и развернуть зависимость?

✍️Повторим все принципы SOLID:
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
  • ❤ 7
  • 👍 4
  • 🔥 4
More from @flutterfriendly
  1. May 14, 2026👀Какой сложный вопрос или тема по Flutter вас сейчас беспокоят? Может, задача не идет, ба…
  2. Apr 17, 2026💭Привет! Это Роза, Flutter-разработчица Friflex! Уверена, многие из вас знакомы с Dart De…
  3. Apr 8, 2026Привет, друзья! Делимся нашей страничкой на Хабре, чтобы всегда оставаться на связи. Там е…
  4. Apr 3, 2026🌸Апрель в календаре и на экране Весна зовет обновлять визуальное: убирать темные темы и в…
  5. Apr 1, 2026Всегда с нетерпением ждем этого дня, чтобы сделать подборку ИТ-мемов Пусть поводов для улы…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →