• Главная
  • Контакты
Подписаться:
  • Twitter
  • Facebook
  • RSS
  • VK
  • PushAll
logo

logo

  • Все
    • Положительные
    • Отрицательные
  • За сегодня
    • Положительные
    • Отрицательные
  • За вчера
    • Положительные
    • Отрицательные
  • За 3 дня
    • Положительные
    • Отрицательные
  • За неделю
    • Положительные
    • Отрицательные
  • За месяц
    • Положительные
    • Отрицательные
  • За год
    • Положительные
    • Отрицательные
  • Сортировка
    • По дате (возр)
    • По дате (убыв)
    • По рейтингу (возр)
    • По рейтингу (убыв)
    • По комментам (возр)
    • По комментам (убыв)
    • По просмотрам (возр)
    • По просмотрам (убыв)
Главная
  • Все
    • Положительные
    • Отрицательные
  • За сегодня
    • Положительные
    • Отрицательные
  • За вчера
    • Положительные
    • Отрицательные
  • За 3 дня
    • Положительные
    • Отрицательные
  • За неделю
    • Положительные
    • Отрицательные
  • За месяц
    • Положительные
    • Отрицательные
  • Главная
  • UIKit + Viper или MVC здорового человека

UIKit + Viper или MVC здорового человека +8

24.04.2017 15:52
atimca 9 3300 Источник
Разработка под iOS*, Swift*
Около года назад я познакомился с таким замечательным паттерном, как Viper. И теперь хочу рассказать о своих проблемах, а так же об их решении.

Введение


Начитавшись туториолов о Viper я начал пробовать создать на нем новый проект. В итоге мой Viper выглядел примерно так:

image

Рядом с каждым блоком подписан базовый класс. Стрелками обозначены ссылки между объектами (пунктиром — weak).

Данная схема не решает крайне важную проблему. Каким образом располагать модули в UINavigationController? Из-за того, что стек навигации необходимо добавлять наследников класса UIViewController.

  • придется в router протягивать view через presenter и явно указывать, что это UIViewController
  • после добавления view в UINavagationController, у view счетчик сильных связей увеличится до 2-х. В последствии придется вручную убирать из памяти viper модуль.

В таком подходе очевидна некоторая несовместимость Viper и UIKit.

Как подружить Viper и UIKit


В первую очередь необходимо понять, как перейти от Apple MVC к Viper. MVC достаточно легко раскладывается на view, presenter и interactor. Но у viper появляется еще дополнительный слой — router. И на этом моменте я предлагаю альтернативную точку зрения(во всяком случае на просторах интернета я ничего подобного не видел).

image

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

В ней сказано:
Presenter/Презентатор

Presenter — это PONSO, который в основном состоит из логики, чтобы управлять UI. Он собирает входные данные от взаимодействия с пользователем, таким образом, он может отправлять запросы Interactor'у. Presenter также получает результаты Interactor'а и преобразовывать результаты в состояние, которое является наиболее эффективным для отображения на View.

Entity никогда не передаются из Interactor'а к Presenter'у. Вместо этого простые структуры данных, у которых нет поведения, передаются из Interactor'а к Presenter'у. Это препятствует любой ‘реальной работе’ в Presenter'е. Presenter может только подготовить данные для отображения на View.

Если в качестве presenter взять не PONSO, а UIViewController, что изменится? Да presenter начнет отвечать за отображение модуля, но только под капотом UIKit. Все методы жизненного цикла, можно расценивать по такому же принципу, как события от кнопок view. То есть view сообщает presenter, что случился viewdidload и с этим можно что-то сделать. Вся логика отрисовки осталась на view.

Теперь давайте рассмотрим router(в статье изображен, как wireframe. Я обычно разделяю на router и moduleManager)

Wireframe/Каркас

Маршрутизация обрабатывает навигацию от одного экрана к другому, как определено в wireframes, созданных проектировщиком взаимодействия. Wireframe объект несет ответственность за маршрутизацию. Wireframe объект владеет объектами UIWindow, UINavigationController, и т.д. Он ответственен за создание Interactor, Presenter и View/ViewController и за настройки ViewController. Так как Presenter содержит логику, чтобы реагировать на ввод данных пользователем, Presenter знает, когда перейти на другой экран. Wireframe знает, как это сделать. Итак, Presenter — это пользователь Wireframa.

Встает вопрос. Почему router не может сам являться UINavigationController? Зачем нам еще велосипед, когда в UIKit есть свои роутеры — это UINavigationController и сочувствующие. В подобных классах уже заложена основная логика.

Что решает такой подход?

  • меньше кода, все сделано за нас
  • понятный код, для человека, незнакомого с Viper
  • за работу с памятью теперь отвечает UIKit, руками не придется уничтожать модули
  • простая интеграция со сторонними библиотеками, которые на входе принимают UIViewController

В качестве примера я создал небольшой демо проект. Надеюсь на объективную дискуссию.
Поделиться с друзьями
-->

Комментарии (9)


  1. rsi
    24.04.2017 20:23
    #10189160
    +1

    У вас вышела некая школьная/упрощенная версия Вайпера. В целом архитектура не плохая и ее можно использовать при этом не прикладывая много усилий в борьбе с uikit. Но это не вайпер, так как основаная идея вайпера это соблюдение принципов solid. А в вашей версии они все нарушены, слишком многого ответственностей на каждом из компонентов. Увеличена связность, тестировать сложнее. Но думаю для мелких проектов и проектов где на первом месте скорость разработки, оно зайдёт.


    1. atimca
      24.04.2017 20:43
      #10189190

      Спасибо за комментарий! Если вам не сложно, опишите пожалуйста подробно, где я что нарушил? Все-таки эта статья была больше написана для того, чтобы разобраться самому почему так делать не стоит и как правильно


      1. rsi
        25.04.2017 04:28
        #10189546

        Еле коротко то вы все нарушили. Начнем с роутера, это компонент отвечающий за переход от одного модуля к другому, UINavigationController отвечает за все что угодного кроме этого, фактически это контейнер для контроллеров, он не знает куда надо переходить дальше. UIViewController опять же не разделим с View он управляет анимацией, навигацией и даже просто внешним видом. Он фактически весь состоит из того чего в нем быть не должно. С interactor`ом и view у вас особых проблем нет, так как они остались из изначального вайпера. Почитайте про solid, поймете что ваша архитектура не про него. Попробуйте покрыть модуль тестами и снова поймете что у вас проблемы. Ваша архитектура это скорее MVC от эапла как она должна быть + interactor. Это лучше чем просто massive view controller, но не более.


        1. atimca
          25.04.2017 09:05
          #10189664

          Было бы прекрасно, если бы вы дали пример, где можно увидеть более правильное построение вайпера. Так-как я видел только достаточно костыльные реализации


          1. rsi
            25.04.2017 09:19
            #10189684

            Можно в шаблонах для generamba посмотреть
            например
            https://github.com/rambler-digital-solutions/generamba-catalog/tree/master/swifty_viper


            1. atimca
              25.04.2017 10:25
              #10189780

              Спасибо! В данном примере получилось тоже самое, только вид с боку. По сути весь модуль держит вью, что на мой взгляд не есть хорошо. Так-же презентер просто ждет сигнала от вью в методе viewIsReady, в своей статье я сделал на этом акцент, что все то-же самое можно сделать, если прентер и будет viewcontroller'ом. Но вот никак не раскрыто, что делать с navigationController и ему подобными.


              1. rsi
                25.04.2017 10:30
                #10189794

                Я вам объяснил что это не то же самое, в презентере нет ничего лишнего, он ничего не знает о view, его легко тестировать, его легко понять, у него всего одна ответственность. То что модуль в памяти держит View это издержки архитектуру apple, и пусть это не лучший вариант, он равно намного лучше чем делать презенте из VC.


  1. DnV
    24.04.2017 21:52
    #10189280
    +1

    «MVC здорового человека» — звучит вызывающе. А я бы назвал статью «Как придумать себе проблемы». Если лыжи не едут, то логично их смазывать, а не приделывать к ним педали.


  1. Krizai
    01.05.2017 22:46
    #10199018

    Один из бенефитов вайпера, это упрощение тестирования компонентов за счет соблюдения solid ( как уже было скзаано выше). Как вы предполагаете тестировать ваши компоненты, если бОльшая их часть завязана на UIKit?

МЕТКИ

  • Хабы
  • Теги

Разработка под iOS

Swift

ios

viper

UIKit

MVC

СЕРВИСЫ
  • logo

    CloudLogs.ru - Облачное логирование

    • Храните логи вашего сервиса или приложения в облаке. Удобно просматривайте и анализируйте их.
Все публикации автора
  • UIKit + Viper или MVC здорового человека +8

    • 24.04.2017 15:52

    Из инженера в iOS-программисты +8

    • 15.03.2017 10:33

Подписка


ЛУЧШЕЕ

  • Сегодня
  • Вчера
  • Позавчера
09:01

Пора начинать использовать интернет как в конце 90-х +46

07:27

Великий Калужский Нефтяной Мираж: как гражданин РФ на патентах поднял десять миллиардов рублей с рынка облигаций +44

14:05

Sony CMD-J7: шедевр инженерной мысли из 2001'ого +19

13:01

Трекеры и чиптюн на AdLib +18

08:00

ИИ добрался до Ubuntu +15

07:05

Рождение легенды: Need for Speed +14

05:32

Кто на чём шлёт и принимает почту: измеряем email-инфраструктуру 660 тысяч доменов из Tranco top-1M +14

18:54

Что там с Ту-214 +11

11:30

КлокВоркПанк +10

15:19

Как определить, что текст был создан с помощью ИИ: гибридный лингвистический подход +9

13:30

Обрекли на учебники: как праиндоевропейцы развалили свой язык +9

09:15

Как я собрал на DGX Spark приватный AI-сервер, и теперь рассказываю, что туда вошло +9

05:48

Понять Big O раз и навсегда +9

00:41

Как сделать локальный генератор изображений через ComfyUI +9

15:48

Как за 300 рублей и 6 часов получить прошивку уровня синьора? +7

13:27

Почему Big Data стек небезопасен по своей природе +7

08:03

Необычная причина для колонизации космоса +7

16:46

Как шифровать сообщения в любом мессенджере и соцсети +6

16:11

Как устроен Meshtastic, зачем он нужен и как я подключил его к локальной модели на ноутбуке +6

14:16

Удаленное управление стройкой за 3 500 км: нулевой цикл, смета и ошибки планирования +6

09:01

Good night, sweet prince: Удафф.ком закрыт, press F to pay respect +61

21:17

Когда каждый лид на счету, или как Лена Понты_По_Колено пиарилась на ИИшечке +56

16:31

РКН объявил войну зарубежным разработчикам игр. Почему это бьёт по всей IT-отрасли +56

13:59

Концепция Байесовского мозга, или Почему этот заголовок в моменте — ваша галлюцинация +54

14:42

Запрещённая математика в твоём autograd: бесконечно малые, дуальные числа и нестандартный анализ +47

11:05

«Черепашки-ниндзя» или как весь мир полюбил пиццу +38

12:13

4 научных доказательства того, что люди реально высаживались на Луну +26

18:45

Простой способ сделать мессенджер Макс безопаснее без Docker и прокси +25

13:00

Неизбежный провал «Halo 4», или почему спринт — это плохо +23

08:38

Меня продали как мидла с 4 годами опыта. Мне было 0. Как я выжил и чему научился +18

08:00

Intel Core Series 3 (Wildcat Lake): новые бюджетные чипы для ноутбуков и мини-ПК +16

23:19

Реализация модульной архитектуры прошивки методом ручной динамической линковки на примере STM32 +11

06:46

Что именно я понимаю под промежуточным представлением (IR) компилятора +9

11:27

Я создал эмулятор Game Boy на F# +8

18:16

Дуров стену не вернул, поэтому я написал свою – агрегатор Telegram-каналов на Telethon +7

12:38

Производительность софт NVMe рейдов на основе mdadm, LVM и ZFS при использовании iSER и NVMe-oF (100G version) — Part 2 +7

07:57

Рассказ о поездке на конференцию инди-разработчиков «Игровая индустрия 2026» в Минске +7

07:10

Процессоры становятся дороже: как ИИ влияет на доступность железа +7

14:18

Плагин шорткодов для Joomla +6

14:17

«Опенсорс + ИИ = Китай»: как открытые языковые модели помогли стране ворваться в гонку +6

05:06

Мне прислали фишинг под MAX. Я разобрал ссылку и нашёл уязвимость в их API +340

09:13

Центры обработки данных в космосе — это ужасная, кошмарная и совершенно бесполезная идея +74

12:09

f4 0.1.1-alpha: первый публичный релиз асинхронного клона Far Manager на Go +66

13:01

Электровакуумные геттеры. Бариевые газопоглотители +50

08:05

Палиха П-750. Последний телефон с АОН двухтысячных +46

09:01

Вайбкод и безопасность: как не задеплоить уязвимости вместе с фичами +31

08:01

Сколько памяти нужно для жизни: стресс-тест старого и нового железа +24

09:16

Я «нанял» AI-команду разработки и управлял ею через Kanban: опыт на реальном продукте +21

23:08

Промпт-инжиниринг для не-промпт-инженеров +17

10:59

Copy.Fail (CVE-2026-31431) — больше чем LPE +15

14:05

Я люблю «Героев меча и магии», но пару моментов бы поменял +14

07:16

Вы неправильно используете clone() в Rust +12

19:24

Эволюция как река: почему жизнь не блуждает по бесконечному пространству геномов +11

09:49

Чтение на выходные: «Технофеодализм: Что убило капитализм» Яниса Варуфакиса +11

17:18

5 скиллов Claude Code из marketplace, которые я попробовал +10

12:15

Простой мониторинг Synology NAS с Grafana и Prometheus +10

12:15

До встречи на танцполе: роботы теперь обучаются движениям на лету и открывают для себя новый класс задач +9

13:56

Классификация галлюцинаций LLM | «Врага нужно знать в лицо» +8

12:23

Как не сойти с ума в 2026 году +8

21:24

Как мы форкнули undetected-chromedriver и добавили SOCKS5, мультипроцессинг и модуль капчи +7

ОБСУЖДАЕМОЕ

  • Центры обработки данных в космосе — это ужасная, кошмарная и совершенно бесполезная идея +75

    • 206   14000

    РКН объявил войну зарубежным разработчикам игр. Почему это бьёт по всей IT-отрасли +56

    • 194   47000

    Мне прислали фишинг под MAX. Я разобрал ссылку и нашёл уязвимость в их API +340

    • 122   27000

    Карпатый объяснил, почему ваши навыки программирования скоро станут ненужными. Или нет -14

    • 103   14000

    4 научных доказательства того, что люди реально высаживались на Луну +26

    • 99   13000

    Улучшать себя или создавать «других»? Делегирование субъектности опаснее, чем апгрейд собственного мозга -1

    • 94   7600

    f4 0.1.1-alpha: первый публичный релиз асинхронного клона Far Manager на Go +66

    • 67   13000

    Концепция Байесовского мозга, или Почему этот заголовок в моменте — ваша галлюцинация +54

    • 61   15000

    Я люблю «Героев меча и магии», но пару моментов бы поменял +14

    • 51   18000

    «Ты врёшь, считая себя просто кучей кода» — ночной разговор с Claude о создании цифровой сущности -2

    • 50   9300

    Эволюция как река: почему жизнь не блуждает по бесконечному пространству геномов +11

    • 50   18000

    Пора начинать использовать интернет как в конце 90-х +47

    • 47   15000

    Кто смотрит ваши видеокамеры? -4

    • 47   9100

    Lolka вместо Discord: обзор молодого российского сервиса для общения -1

    • 42   17000

    Мы снова строим новое рабовладельческое общество. Только рабы – цифровые? +2

    • 41   13000
  • Главная
  • Контакты
© 2026. Все публикации принадлежат авторам.