Connect with us

Программирование

Однонаправленный поток в Swift

Но как быть с type-safe системой управления состояниями? Как ее построить, используя возможности языка Swift?

Опубликовано

/

     
     

На этой неделе я расскажу о подходе к управлению состояниями, который я использую в своих приложениях уже много лет. Мы рассмотрим построение предсказуемой, тестируемой, отлаживаемой и модульной системы управления состояниями в Swift.

Swift способствует созданию type-safe кода, используя набор возможностей языка, позволяющих кодировать правильное поведение в системе типов. Мы стремимся моделировать наши типы таким образом, чтобы логическая ошибка становилась ошибкой времени компиляции, а не времени выполнения. Для этого используются типы значений, перечисления, опции, протоколы, дженерики, фантомные типы и т.д.

Система управления состоянием

Но как быть с type-safe системой управления состояниями? Как ее построить, используя возможности языка Swift? Мы применим те же инструменты для построения функциональной и безопасной системы управления состоянием.

Вот базовый пример системы управления состоянием, которую мы можем сделать в Swift. Мы выражаем тип Store, который определяет два общих типа: один для состояния, другой для действия. Он хранит текущее состояние в переменной, которую мы можем мутировать только внутри типа Store. Он также предоставляет нам функцию send, которая принимает в качестве параметра общее действие и мутирует текущее состояние. Весь тип помечен макросом Observable, что позволяет нам получать уведомления о каждом изменении состояния.

Предсказуемая

Первая цель при построении системы управления состоянием, которую мы хотим достичь, — сделать ее предсказуемой. Как видно из приведенного примера, единственным способом изменения состояния является отправка предопределенного действия. Все представления и контроллеры представления в вашем приложении берут экземпляр типа Store и могут читать только фактическое состояние. Не существует способа изменить что-либо в состоянии напрямую. Единственным способом обновления состояния является отправка действия.

Функция reduce — это единственное место, содержащее логику обновления состояния. Это не означает, что нужно иметь одну функцию для всего приложения. Вы можете объединить несколько функций reduce в одну. Обычно у меня есть функция reduce для каждого функционального модуля моего приложения.

Как видно из приведенного примера, мы определяем список, в котором отображаются товары. Мы также позволяем удалять товары из списка с помощью свайпов. Представление имеет доступ к состоянию только для чтения и может отображать его как есть. Единственный способ изменить состояние — использовать функцию send с одним из предопределенных в перечислении ShopAction случаев.

Такой подход называется однонаправленным потоком. Как следует из названия, движение осуществляется только в одном направлении. Представление посылает действия, магазин обновляет состояние, а представление принимает обновленное состояние. Применяя этот подход, мы делаем управление состоянием предсказуемым. Вы всегда знаете, где искать мутацию и где находится бизнес-логика вашего приложения.

Тестируемая

Как мы уже говорили, логика приложения находится в функции reduce. Это чистая функция, которая принимает в качестве параметров текущее состояние и действие, которое нужно применить, и возвращает новое состояние. И состояние, и действие являются типами значений. Обычно мы используем структуру для состояния и перечисление для действия. Это означает, что мы можем легко проверить любые функции reduce в модульных тестах.

Все, что нам нужно сделать, — это создать начальное состояние и вызвать функцию reduce с определенным действием. Затем мы можем убедиться, что новое состояние, возвращаемое функцией reduce, содержит все необходимые изменения.

С предварительным просмотром

Этот подход отлично работает с предварительным просмотром в Xcode. Можно создать несколько превью с различными начальными состояниями. Например, одно для пустого списка, другое — для списка товаров. При этом нет необходимости в мокировании протоколов, поскольку состояние представляет собой простую структуру, которую можно создать и поместить в хранилище для отображения в представлении.

Отлаживаемая

Отладка и логирование стали очень простыми. Если что-то идет не так, вы знаете, где искать. Функция reduce — единственное место, содержащее логику приложения, и это лучшее место для размещения сообщений логов, поскольку все действия проходят через функцию reduce. Это означает, что ваши журналы никогда не пропустят ни одного изменения состояния.

Храня состояние функции в одном месте, мы можем легко отслеживать историю изменения состояния. Это поможет нам понять, какая последовательность действий привела к ошибке. Мы также можем закодировать состояние в JSON и получить его для анализа или восстановить под отладчиком для проверки ошибки.

Модульная

Многие мои коллеги сравнивают однонаправленный поток с single-state контейнером, где все состояние приложения хранится в одном экземпляре определенной структуры AppState. Да, это возможно, но это не единственный путь.

Обычно я определяю хранилище для каждой функции. Таким образом, каждая независимая функция имеет свое собственное хранилище. Это позволяет оптимизировать производительность, поскольку в случае огромного приложения наличие одного хранилища может привести к снижению производительности, когда вся иерархия приложения обновляется при каждом небольшом изменении состояния.

Ссылки

После нескольких лет создания подобных приложений эти идеи вылились в Swift-пакет под названием Swift Unidirectional Flow. Он реализует все обсуждаемые нами идеи в готовом к производству коде, поддерживающем параллелизм и другие возможности, которые могут понадобиться при создании реального приложения.

Я не настаиваю на использовании этого пакета. В частности, не следует импортировать сторонние библиотеки или фреймворки для создания основных функций вашего приложения. Но вы можете использовать его для вдохновения, чтобы построить систему управления состояниями в своем приложении с учетом ваших потребностей.

Заключение

Надеюсь, вам понравилась эта статья. Не стесняйтесь следовать за мной в Twitter и задавать свои вопросы, связанные с этой статьей. Спасибо, что прочитали, и до встречи!

Еще про однонаправленные потоки

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: