При использовании чистой архитектуры с флаттером мы видим диаграмму, подобную этой:
(В качестве примера я написал пакет MobX, но это может быть что угодно вроде BLoC, Redux ...)
У меня могут возникнуть проблемы с этой диаграммой, поскольку Магазин находится на уровне представления и отвечает за изменение состояния.
Представьте, что приложение загружает список задач с помощью метода getTodos Implementend в TodosStore. Реализация getTodos может быть такой:
_state = State.loading();
final result = GetTodos();
_state = State.done();
(Я слишком упрощал)
Он начинается с обновления состояния до загрузки, вызывает вариант использования, возвращающий список, и устанавливает состояние в состояние «Готово».
Проблемы, которые я нашел здесь:
- Магазины несут ответственность за вызов UC, обновление состояния, обработку ошибок ...
- Вариант использования - это просто мост, который не обрабатывает бизнес-логику
Это довольно простой пример. Но давайте представим, что у меня есть представление с тремя списками разных данных (это может быть абсурдный пример). Представление взаимодействует с 3 разными магазинами. На панели приложения есть кнопка. Его цель - очистить 3 списка.
Как добиться такого поведения?
- Метод кнопки onPressed должен будет вызывать clearData для каждого магазина.
- Метод очистки каждого магазина просто обновит его свойства.
Дело в том, что вид не такой тупой, как хотелось бы. Магазин даже не взаимодействует ни с одним вариантом использования
Должен ли быть здесь законный вариант использования ClearLists?
Поскольку мне не нравится много логики на уровне представления, я стараюсь следовать этой диаграмме:
Каждое представление имеет свою собственную ViewModel. ВМ просто взаимодействует с вариантом использования. Эти UC могут возвращать или не возвращать значение. Например: мой UC - это ValidateNumberRange, я могу не взаимодействовать с магазином. Имеет смысл вернуть bool. Но если мой UC - ClearTodoList, он может взаимодействовать с магазином. Успех или неудача могут быть сохраненным значением. Таким образом, возврат значения может оказаться бесполезным.
На этой новой диаграмме реализация вызываемого метода варианта использования GetTodos может быть следующей:
store.set(State.loading());
final result = repo.getTodos();
result.fold(
(failureMsg) { store.set(State.failure(failureMsg)); },
(newList) { store.set(State.done(newList)); },
);
- Вариант использования обрабатывает логику управления состоянием
- View вызывает метод виртуальной машины. Виртуальная машина вызывает UC и отслеживает изменения в Store (здесь через MobX)
Я задаю себе массу вопросов:
- Правильно ли я понял роль UC в чистой архитектуре?
- Считается ли изменение состояния (загрузка, выполнение, сбой) бизнес-логикой?
- Где бы вы поместили решение для управления состоянием в своем приложении?
Я с нетерпением жду ваших мыслей