MVC был давним стандартом в паттернах проектирования, используемых для написания iOS приложений. Структура iOS приложений, которые создавались ранее, была основана на одном базовом компоненте, который присутствует везде, и называется он — view controller. На WWDC19 был представлен SwiftUI, который не имеет такого компонента.
Проблема с так называемыми massive view-controllers должна быть решена в SwiftUI. Так, необходимо найти новый способ правильной декомпозиции кода. Давайте посмотрим на текущее состояние платформы и подумаем, какие парадигмы мы можем использовать при разработке для iOS13, и более поздних версий.
Однонаправленные и двунаправленные архитектуры
Большенство архитектурных решений которые используют крупные корпораций являются двунаправленными. Это означает, что вы можете думать о них как о слоях друг над другом и они могут общаться между собой передавая данные как вверх, так и вниз. Такие шаблоны, как MVC, Model-View-ViewModel и даже многие реализации паттерна MVVM с координаторами, также являются двунаправленными архитектурами.
Примером широко используемого в настоящее время однонаправленного потока данных на платформе iOS является цикл VIP (представление-интерактор-презентатор) в архитектурах Clean Swift или Viper. Эти архитектуры не являются чисто однонаправленными. Router и исполняемые модули связываются с циклом VIP в обоих направлениях.
Еще одну вещь, которую мы можем наблюдать, это то, что шаблон MVC и другие паттерны, которые построенные на его основе, в большей степени основаны и располагаются на одном экране. Обычно не существует четкой структуры для сервисов, исполнительных модулей и т. д., которые взаимодействуют с различными частями приложения.
Data flow в SwiftUI
Согласно презентации WWDC, элемент, соединяющий view и model/state в SwiftUI, был некий класс Store, соответствующий протоколу BindableObject. Нам остается только надеяться, что у нас не будет приложений с massive store, содержащим всю логику приложения со всеми состояниями без какой-либо четкой структуры. Я считаю, что мы, как сообщество, достаточно продвинуты и можем добиться большего успеха в этом направление.
Если мы поместим MVC и SwiftUI с view и store рядом друг с другом, мы сможем увидеть почти один и тот же шаблон, который может привести к аналогичным проблемам, которые были у нас с контроллером представления, но без какого-либо стандартного кода, что VC имеет по своей природе.
Если вы поместите MVC и store в диаграмме, они могут выглядеть примерно так.
На первый взгляд может показаться, что Combine может быть архитектурным паттерном, используемым в SwiftUI. Но Combine — это всего лишь инструмент для обработки значений во времени. Точно так же MVVM, использующий RxSwift, по-прежнему MVVM, просто связь между уровнями, которая реализуется разными способами.
Декларативная архитектура для декларативных пользовательских интерфейсов
SwiftUI может быть кратко изложен в нескольких словах, таких как декларативный пользовательский интерфейс. Я считаю, что можно добиться большего, если мыслить нестандартно и сосредоточиться на слове «декларативный». Самые передовые декларативные архитектурные примеры могут быть найдены при разработке front-end приложений. Такие концепции как ELM, Redux и Flux могут быть легко использованы с инфраструктурой SwiftUI и Combine. Для Swift уже было несколько повторных реализаций таких, как ReSwift, но все же необходимым было бы объединить эти реализации в Combine.
Слегка измененный Data Flow в SwiftUI из WWDC19
Мне бы хотелось поиграть с SwiftUI с самого начала без каких-либо зависимостей, и в настоящее время я экспериментирую в Swift с простой реализацией архитектуры ELM. Эта архитектура лучше соответствует диаграммам, которые Apple показала на WWDC.
Мы можем описать приложение посредством данных архитектурных паттернов:
- Action — это тип, описывающий все события, которые могут произойти в приложении. (В простом приложении это может быть enum с некоторым связанным значением, в крупномасштабном приложении можно использовать множество структур, соответствующих протоколу действий.)
- Update (или reducer в Redux) — это простая чистая функция, которая принимает текущее состояние и отправленное действие и возвращает новое измененное состояние. (Эти функции не создают сайд эффектов и могут быть легко объединены.)
- State — это тип, описывающий состояние приложения. (Простой список задач, может использовать массив.)
Все эти три элемента являются декларативными, и каждый из них представляет собой одну небольшую тестируемую и многократно используемую часть головоломки, которая вместе составляет целое приложение. Состояние хранится в Store, и представление может быть вычислено из него.
State, Actions и update для простого приложений на Swift.
Для асинхронных операций мы могли бы ввести что-то вроде объекта middleware в Redux или Commands в ELM.
Заключение
Мы можем либо использовать любые известные нам архитектуры, и когда мы постепенно добавим SwiftUI к существующим в настоящее время приложениям, это будет надежным и безопасным подходом. В случае, если реализуется новое приложение используя только SwiftUI, можно использовать более открытый подход и попробовать что-то другое.
Если вы задумаетесь о разработке приложения с использованием SwiftUI в ближайшее время, я бы порекомендовал обратить внимание на некоторые моменты:
- Apple не предоставляет детального руководства по архитектуре приложений, это означает, что у нас как у сообщества программистов есть много возможностей для инноваций и реализаций новых подходов.
- Мы определенно увидим гораздо более широкий масштаб различных кодовых баз, поскольку дыра, оставленная после контроллера представления, должна быть заполнена.
- Сохраняйте открытость и не бойтесь начинать с нуля.
Мои эксперименты можно найти в playground Swift (для сравнения – представлена реализации и использовании UIKit и SwiftUI, одного и того же приложения).
Следующие шаги
Существует много способов, которыми мы можем воспользоваться, но я настоятельно склонен наконец опробовать гораздо более функциональный подход к разработке приложений. Так, можно увидеть некоторые интересные решения от сообщества, и у нас все еще есть довольно много времени, когда мы сможем использовать SwiftUI в повседневной работе, так что еще есть время для экспериментов и никакого давления на нас не оказывается.
Я планирую написать больше об этой реализации однонаправленной и функциональной архитектуры. Я надеюсь, что скоро смогу использовать это в каком-нибудь небольшом реальном проекте, поэтому я смогу подробнее рассказать о том, насколько этот подход жизнеспособен и имеет проблемы с производительностью в крупномасштабных проектах.
Автор: Dima