Какие архитектурные паттерны для слоя представления (UI) ты использовал во Flutter?

Ответ

На уровне UI (Presentation Layer) я фокусируюсь на паттернах, которые управляют состоянием экрана и логикой отображения. Вот основные из них в моей практике:

  • MVVM (Model-View-ViewModel): Чаще всего я использую именно этот подход. ViewModel (часто реализованный как ChangeNotifier или с помощью StateNotifier из Riverpod) содержит состояние и логику для View (виджета Flutter). Связь между ними осуществляется через слушатели или провайдеры.

    // ViewModel для экрана входа
    class LoginViewModel extends ChangeNotifier {
      String _email = '';
      String _password = '';
      bool _isLoading = false;
    
      // Геттеры для View
      bool get isValid => _email.isNotEmpty && _password.isNotEmpty;
      bool get isLoading => _isLoading;
    
      void updateEmail(String value) {
        _email = value;
        notifyListeners();
      }
    
      Future<void> submit() async {
        _isLoading = true;
        notifyListeners();
        // ... вызов use case или репозитория
        _isLoading = false;
        notifyListeners();
      }
    }
  • BLoC (Business Logic Component): Когда логика экрана становится сложной и включает множество событий, я выбираю BLoC. Он идеально подходит для экранов с формами, фильтрами, реальным временем. Я использую пакет flutter_bloc, который предоставляет четкую структуру Bloc, Event, State и виджеты BlocBuilder/BlocListener для реакции на изменения.

  • Presenter/Controller (в рамках Clean Architecture): В проектах с Clean Architecture роль ViewModel часто играет Presenter или Controller. Его задача — принимать данные от Use Cases (из Domain слоя), преобразовывать их в модель, удобную для отображения (UiModel), и управлять состоянием загрузки/ошибок. View в этом случае становится максимально "тупым" и просто отрисовывает переданную UiModel.

  • StatefulWidget как простейший паттерн: Для очень простых экранов без сложного состояния (например, статический экран "О приложении") можно обойтись встроенным StatefulWidget. Однако для всего, что сложнее, я сразу применяю один из вышеперечисленных паттернов, чтобы обеспечить тестируемость и разделение ответственности.

Ответ 18+ 🔞

Слушай, а вот про UI-слой, это же вообще отдельная песня, ёпта. Ты представляешь, сколько там этих паттернов развелось, как будто на выставке собак — каждый кобель норовит свою родословную показать. Я тебе сейчас по полочкам разложу, на чём обычно строю, чтобы не было потом пиздопроебибны в коде.

MVVM (Model-View-ViewModel) — это мой, можно сказать, рабочий конёк. Ну то есть, не конёк, а вообще основа основ. Смысл в чём: ViewModel — это такая хитрая жопа, которая всю логику экрана в себе держит, а View (то есть виджет) просто тупо рисует то, что ему сказали. Связываю я их обычно через ChangeNotifier или, если проект посерьёзнее, через StateNotifier из Riverpod. Получается чисто, понятно, и тестировать можно.

// ViewModel для экрана входа
class LoginViewModel extends ChangeNotifier {
  String _email = '';
  String _password = '';
  bool _isLoading = false;

  // Геттеры для View
  bool get isValid => _email.isNotEmpty && _password.isNotEmpty;
  bool get isLoading => _isLoading;

  void updateEmail(String value) {
    _email = value;
    notifyListeners(); // Крикнул виджету: "Э, бошка думай, данные обновились!"
  }

  Future<void> submit() async {
    _isLoading = true;
    notifyListeners();
    // ... тут вызов use case или репозитория, где всё может накрыться медным тазом
    _isLoading = false;
    notifyListeners();
  }
}

BLoC (Business Logic Component) — это уже когда MVVM начинает потеть и задыхаться. Беру его на вооружение, если на экране начинается настоящий ёперный театр: куча событий, сложные переходы состояний, фильтры в реальном времени. Пакет flutter_bloc — просто песня, там всё чётко: Bloc, Event, State. Сидишь и как дирижёр оркестром управляешь этим цирком через BlocBuilder и BlocListener. Удивление пиздец, насколько удобно.

Presenter/Controller (в рамках Clean Architecture) — а это уже для проектов, где все такие серьёзные, в очках и с архитектурными диаграммами. Тут Presenter — это такой переговорщик между бизнес-логикой (Use Cases) и тупым виджетом. Его задача — взять сырые данные, отформатировать их в красивую UiModel (чтобы виджет не ломал голову) и ещё за всеми этими состояниями загрузки-ошибок следить. Виджет в этой схеме становится настолько тупым, что ему хоть вилкой в глаз, а он только картинки менять будет.

StatefulWidget как простейший паттерн — ну это, бля, как взять молоток и гвозди, чтобы собрать табуретку. Для экрана «О приложении», где одна картинка и два текста — ещё куда ни шло. Но чуть что посложнее — и ты уже сидишь с этим setState, который раскидан по всему виджету, и чувствуешь себя полным распиздяем. Поэтому я, как только вижу, что состояние хоть чуть-чуть выходит за рамки «включено/выключено», сразу хватаю MVVM или BLoC. И тестировать потом можно, и голова не болит, и доверия к коду — не ноль ебать, а вполне себе есть.