VIPER в интерпретации Rambler вошел в мир iOS достаточно давно. Написана отличная книга и в связке с приложением «Конференции» дает исчерпывающее представление о заложенных подходах в Clean Architecture и SOLID. Но с одним недостатком — все на Objective-C.
TECHNOLOGY RADAR еще в апреле 2016 сделал swift в качестве основного языка разработки под iOS. А у нас на дворе 2k17 и swift 4. А что это значит? Правильно! Пишем свое приложение с блекджеком и RxSwift!
Получилось приложение прогноза погоды в котором используются следующие технологии:
Ознакомится с приложением можно на github’e — https://github.com/trykovyura/Swift-Viper-Weather-App
Intro
За основу был взят пример SwinjectSimpleExample и переработан полностью. Первый релиз в итоге вышел на swift 3 т.к. не все библиотеки успели обновить до 4 версии swift. Занесем это в список TODO.
VIPER
Про ньюансы swift с viper рассказывали на выступлении Rambler.iOS #5: SWIFT + VIPER (Попов Валерий).
Первый вопрос который следует рассмотреть это DI. Ребята пошли на инициализацию модулей через Storyboard objects. Сделано аналогично. Только со щепоткой Swinject для работы с Assembly других слоев. Application, Business, Core слои собираются через Swinject.
Второй вопрос это взаимодействие между модулями — moduleInput, moduleOutput. В ObjC версии есть ViperMcFlurry. С ним можно работать и в swift, но оставим это на TODO. Взял уже готовую обертку LightRoute с ограничением по moduleOutput.
Moya
Закрывает работу с сетью абстракцией.
Много расширений для работы с сетевым слоем. Воспользовались mapping’ом для JSON.
Кто то скажет overhead? Да это можно написать и самому и тащить из проекта в проект. Кому что ближе. Может кто не переносит alamofire. Но рекомендую присмотреться.
RxSwift
Использован только на уровне бизнес слоя для работы с сетью. Если в objc chain запросов решался через COOperations, то в swift гораздо приятней и удобней это делать через Rx.
Работу в фасадах с Rx запишем в TODO.
Выносить на UI не стал ибо черевато выстрелами в ноги. Хорошего по немногу. Единственное можно для строки поиска debounce сделать.
Realm
Заметное отличие от CoreData — это возможность указать Primary Key для обновления объектов при сохранении. В остальном будем посмотреть.
В андроиде RxRealm идет из коробки. Для iOS на выручку идет RxSwiftCommunity. Запишем это в TODO.
Работа с Realm абстрагирована Repository. Хотелось по максимум возможности swift применить, но он не идеален и работа с конструкторами это прям боль.
По итогу
Часто в production не пропихнуть новую библиотеку или новый подход без детального понимания тех преимуществ, которые они несут. Не каждый бизнес захочет тратить время на рефакторинг и не каждый тим лид выделять время для команды.
Для этого пишутся вот такие демо приложения в качестве proof of concept и ознакомления с последними библиотеками.
Составлен TODO список — засылайте свои pull request’ы, форкайте, показывайте коллегам.
А почему ты не все объекты через Swinject резолвишь, а только сервисы?
https://monosnap.com/file/OvLFCbphWIShm5ADAbYtUDZwUSrvBM.png
В моем понимании конфигурирование модуля через инициализатор object в storyboard представляет из себя assembly модуля.
И нецелесообразно делать матрешку assembly: Initializer -> Configurator -> Module Assemble(swinject). В конфигураторе тогда будет 1 строка вызова Module Assemble(swinject). Его наличие в цепочке уже под вопросом. К тому же в Module Assemble надо передавать VC.
Если начать резолвить все через swinject, то целесообразней использовать SwinjectStoryboard
и отказаться от object initializer.
Для SwinjectStoryboard требуется зарегистрировать в контейнере все storyboard и vc. Что при наличии большого числа экранов может ударить по времени старта приложения.
Разбор плюсов и минусов di контейнеров и object Initializer можно глянуть тут https://www.youtube.com/watch?v=m4MYKzlqtH8