В последние несколько лет я встретил множество проектов, разработчиков и статей, которые обвиняют Model-ViewController архитектуру во многих, если не во всех бедах, которые происходят в iOS-сообществе.

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

Начнем с того, что такое MVC. Все мы видели эту красивую диаграмму из документации:

?image

В теории все довольно красиво, так же как и на диаграмме, view передает действие пользователя controller’у, он в свою очередь если необходимо обновляет модель, модель после завершения обновления уведомляет controller, и он же обновляет view. Все просто, все работает. Используя данный подход были написаны десятки, если не сотни тысяч приложений, в том числе и крупные, и я имею ввиду не только iOS, ?MacOS — Web приложения, Windows приложения и многое другое использует этот подход на протяжении уже почти 40 лет. Многие из них используют этот подход и сегодня, и при этом не испытывают никаких проблем.??Основные достоинства MVC — простота в использовании, особенно в iOS. UIViewController и его наследники в UIKit framework дают очень много функционала и возможностей “из коробки“. Для написания маленьких приложений практически не требуются навыки программирования, достаточно пары дней YouTube лекций и можно начинать. ?Проблемы же начинаются когда вам нужно работать на больших проектах. Множество свидетельств того что MVC, как паттерн, очень плохо масштабируется, и это в свою очередь ведет к проблеме, которую называют Massive View Controller. ?

Причины возникновения проблемы

??Причинами же возникновения данной проблемы являются на мой взгляд 2 вещи:

1. MVC действительно не дает вам четких инструкций о том, какие сущности и классы вам нужно создавать, а какие нет. Особенно в iOS. UIKit MVC изначально лишь дает вам UIViewController, и это в принципе и все. View существует, но не декларировано изначально, т.е. даже не создавая отдельный экземпляр view, имея только UIViewController приложение будет выполнять свои функции. То же самое и с моделью. Структура и архитектура модели, а так же ее взаимодействие с controller’ом остаются полностью на совести и воображении разработчика(ов). Это собственно и ведет ко второй причине.

2. Плохое понимание доменной области, неспособность разработчиков выделять необходимые сущности и как следствие накопление зависимостей и функционала внутри UIViewController. Т.е. когда разработчик добавляет новый функционал, вместо создания новых сущностей и рефакторинга существующей архитектуры — добавляется новый функционал во ViewController.

Т.е. я хочу сказать, что проблема возникает в равной степени из-за недостатков архитектуры и невнимательности/халатности/лени/незнания/неопытности (нужное подчеркнуть) разработчиков.

Решения первой проблемы

Довольно популярные в последние несколько лет подходы MVVM, MVP, VIP, VIPER, Flux(Facebook), Riblets (Viper от Uber), Clean-Swift и другие, частично или полностью решают первую часть проблемы MVC. Многие из них дают разработчику(ам) четкие инструкции о том какие классы и для чего необходимо создавать. Так же они значительно облегчают работу в команде, особенно если команда состоит из 10+ разработчиков, которые работают на одном проекте (например в Uber работает 150, JustEats 20+, Facebook даже считать боюсь, но точно более 10 ;) ). Облегчение происходит из-за того, что подразумевается создание большого количества изолированных объектов, только для покрытия Controller кода, это в свою очередь позволяет без особых потерь распределить работу внутри команды.

Вторая же проблема все еще остается. Я встретил множество проектов, которые использовали VIP и MVVM с классами view-models и presenters с более чем 1500 строк кода, содержащих множественные операции, начиная от парсинга и мапинга, заканчивая формированиями запросов в базы данных и http запросами. Проблема неопытности разработчика или непонимания архитектуры приложений в целом не решить простой сменой архитектурного паттерна. С моей точки зрения не существует “золотой пули”, которая позволит вам поддерживать/писать большие и сложные проекты просто “by default“. В любом случае это будет требовать усилий, юнит тестов, грамотного планирования и времени.?

Та часть, где есть советы о том, как частично избегать второй проблемы

1. Облегчаем ViewController

Прежде всего, по хорошему, никакой объект в приложении не должен быть ответственным более чем за 1 функцию (Single Responsibility). Для многих разработчиков это очевидно, но тем не менее их код далеко от соблюдения такого простого постулата. Для многих не очевидно, что UIViewController — это такой же объект как и все остальные, и что у него должна быть только одна ответственность — связывать model и view. Т.е. поддерживать view в соответствующем модели состоянии и оповещать model о том, когда ей нужно менять это состояние. Все, что выходит за пределы этого определения, с моей точки зрения контроллеру не принадлежит. Весь мусор такой как анимации, layout, композиции view, изменение отрисовок, парсинг, мапинг, http запросы, запросы в базы данных, разного уровня сервисы операционной системы и многое другое — это все не принадлежит контроллеру. Ничего из этого не должно создаваться и вызываться внутри контроллера.?Одним из отдельных пунктов должна быть навигация. Если ваш ViewController имеет более чем одну точку выхода, то стоит задуматься о навигации и управлении навигацией. Очень часто приходилось встречать ViewController’ы которые имели 5-10 точек выхода разбросанных по всему коду controller’а. Существует множество способов как это можно организовать, от вынесения навигации в отдельные extension, управлении навигацией исключительно через segue, создании отдельной сущности Router, наследовании UINavigationController и тд. но это тоже нужно делать. И тестировать. ?Главное что нужно запомнить, что ViewController должен делать, то что он должен, а не все под ряд.?То же самое можно сказать и о сущностях, которые используются в MVVM, VIPER (список подлиннее чуть выше). Все они должны выполнять, только то что должны, если это View-Model — то только репрезентация данных для View, если это entity — то хранение и преобразование данных и тд(примеры ответственностей произвольные, автор не претендует на полную истинность этих утверждений). Всегда перед тем как добавить новый метод или свойство к уже существующему классу — задумайтесь о том, действительно ли это должно быть именно в этом классе.

2. Модели

?Одна из ошибок, которую можно довольно часто наблюдать в iOS — это недостаточная изолированность уровня model. С моей точки зрения, и после успешного применения на практике, лучше всего модели выносить в отдельные framework’и. Выносить можно по доменной принадлежности. Для примера, если у вас приложение доставки еды — то в отдельные framework’и можно вынести например: рестораны и все что связано с ними(поиск по ресторанам, меню, расположение и тд), блюда, районы доставки и тд.?Если у вас приложение по покупке авиабилетов то можно выделить десяток farmework’ов (поиск билетов, резервирование, покупка, история и тд). Каждый framework можно покрыть отдельным сетом unit test. ?Можно этого и не делать, но тем не менее стараться писать модели полностью изолированные от любого взаимодействия с контроллерами.

3. Массивные ‘UI’ ViewController’ы

?Я не один раз встречал огромные сториборды(к ним еще вернемся) и не менее огромные UIViewController’ы. Огромные не с точки зрения количества кода(хотя и это тоже), но с точки зрения количества UI элементов. ?Вопрос, который как я думаю должен задать себе каждый разработчик, когда он видит огромный, нагроможденный ViewController, звучит так — “Могу ли я как-то разбить этот VC на меньшие View или VC“.?
?
image

Это скриншот пустого документа в Word, и я очень сомневаюсь, что это 1 ViewController, но при этом очень многие iOS разработчики следуют парадигме 1 экран — 1 ViewController.

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

image

Где каждая ячейка в таблице — отдельный VC. Заголовок с Аватаром автора, автором и временем — отдельный ViewController. Контент и Ссылка — тоже отдельный ViewController.

Like — Comment — Share — все эти компоненты — отдельный ViewController.?

4. Много UI Кода?

Объемный UI код так же может вести к ожирению разных компонентов. Решением может быть дефолтное наследование UI компонентов вместо кастомизации внутри ViewController’а. Или же вы можете добавлять extension’ы для описания UI.?

5. Массивные Storyboard.

??Множество раз я встречал массивные Storyboard файлы в проектах. По 20-50 ViewController с разными уровнями детализации внесены в Storyboard. Вначале все идет гладко и удобно, вся навигация тут как тут, настройки тоже, но как только к проекту меняются требования или же подключаются новые разработчики — это становится полным адом. ?Одно из решений — не использовать Xcode UI Builder как таковой. Создавать весь layout из кода.

Использовать различные библиотеки для упрощения написания constraints(Parus, Masonry т тд.) или же по хардкору использовать CGFrame и под все ориентации и разрешения писать все самому. ?Если же очень хочется использовать Storyboard то задумайтесь о том, чтобы разбить ваш проект на несколько. В идеале Storyboard должен иметь одну ответственность, или один usecase. Т.е. например если у вас приложение для Такси, то отдельными Storyboard’ами могут быть: Вызов такси, Отслеживание такси, Оплата, Общая информация, и тд. Т.е. более менее самостоятельные фичи. Со storyboard reference делать это очень удобно и требует минимум написания кода. В идеале Storyboard не должен содержать больше чем 3-4 отдельно взятых экрана. Чем больше становится storyboard тем больше сил требуется для его поддержки, в нем сложнее разобраться с первого раза, он банально дольше грузится и с ним становится тяжелее работать в группе разработчиков.?

Выводы

??Что хотелось сказать этим постом — это то, что я заметил тенденцию обвинения MVC во многих бедах iOS разработчиков, при этом очень часто(как видно на некоторых примерах выше), эти обвинения не особо относятся конкретно к iOS. Чаще же это вина самих разработчиков, более того, эти разработчики зачастую испытывают те же или схожие проблемы при переходе на другие архитектуры. Massive VC появляется в 90% случаев не потому, что MVC не умеет масштабироваться, а потому, что разработчики не хотят/не позволяют ограничения правильно масштабировать.

VIPER, MVVM (и другие) могут вам помочь с этим, особенно если вы работаете в команде разработчиков, но они не будут для вас панацеей от всех ваших проблем. В статье я лишь попытался привести некоторые из ситуаций в которых MVC — не виноват, и в своем роде выступить адвокатом дьявола, хоть сам и пользуюсь VIPER/MVVM на своих проектах. ?Пишите хороший код. Всем бобра.
Поделиться с друзьями
-->

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


  1. FirsofMaxim
    20.03.2017 22:25
    +1

    Спасибо, тут есть одно из решений для массивных Storyboard — https://habrahabr.ru/post/312766/


    1. PavelGatilov
      20.03.2017 22:43
      +1

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


  1. svistkovr
    21.03.2017 01:19

    Что это за подход такой — давай выкинем все что дает нам Apple и сделаем как у крутых дядек в других конторах.
    Давайте выкинем сториборды, а вместо обычных UIView наклепаем UIViewController со скрытыми методами( у UIViewController есть куча методов базовых для навигации и лайуота). А потом иди ищи где там что отваливается или ненажимается.
    Если вы загоните все констрейнты в код — то как потом через кучу лет разработчикам найти нужный констрейнт и элемент?
    Apple предоставляет хороший подход для разработки своих приложений как для программистов так и для дизайнеров интерфейсов. Люди пишут целые гайды под это дело. Почему никто не читает эти гайды и документацию?

    P.S. Вы упомянули фейсбук с их огромной командой. Но почему тогда приложение фейсбука весит более 130МБ для десятка экранов. Видимо «хорошие спецы» его клепают.


    1. PavelGatilov
      21.03.2017 03:21
      +1

      Что это за подход такой — давай выкинем все что дает нам Apple и сделаем как у крутых дядек в других конторах.

      Где вы увидели выкинем все что дает на Apple? Статья как раз в защиту механизмов предоставленных Apple, в частности подхода к архитектуре и конкретно паттерну MVC.

      у UIViewController есть куча методов базовых для навигации и лайуота

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

      Если вы загоните все констрейнты в код — то как потом через кучу лет разработчикам найти нужный констрейнт и элемент?

      Я не агитировал загонять все констрейнты в код, лишь упомянул о наличии такой альтернативы. И тем не менее вопрос поиска констреинта и элемента лежит полностью на организации вашего кода. Множество проектов на разных языках написаны без использования различный UI билдеров. Ярчайшим примером может служить web-frontend, где весь UI код и элементы описаны при помощи HTML и CSS и не возникает проблем поддержки и поиска.

      Apple предоставляет хороший подход для разработки своих приложений как для программистов так и для дизайнеров интерфейсов

      Множество разработчиков, которым приходилось иметь дело с долгоживущими проектами с вами не согласятся. Многие даже уверены, что Apple видит приложения для своих платформ в несколько ином свете, нежели разработчики современных приложений.

      Почему никто не читает эти гайды и документацию?

      Почему вы думаете, что никто не читает документацию?

      Но почему тогда приложение фейсбука весит более 130МБ для десятка экранов. Видимо «хорошие спецы» его клепают.

      Десятка экранов? Вы же это не серйозно.
      К тому же я считаю, что размер приложения — далеко не показатель качества написания кода.
      Более того, вот развернутый реверс их iOS App
      Я думаю, что очень многое продиктовано требованиями продукта. Думаю только одни кастомные эмоджи на экране лайков — 20-30 классов.
      И да, я считаю, что у многих спецов из Facebook есть чему поучится.


      1. FirsofMaxim
        21.03.2017 09:36

        Насчет Facebook, я удалил его с моего iPhone5s (сейчас хожу через Хром в телефоне), жрал 35% батарейки, не уверен — относится это к качеству?


        1. PavelGatilov
          21.03.2017 12:45

          Тоже не уверен. Без знания бизнес требований к продукту очень сложно судить по единичным параметрам. Вполне могу себе представить ситуацию, когда требования от PO или BA были что-то вроде: «Нужно отправлять геолокацию на сервер каждые 15 секунд, это нужно для аналитики» или «нужно обрабатывать граф друзей при каждой загрузке фида для отправки нового запроса на рекомендации в друзья» и т. д.
          Опять таки, не думаю, что в компании в которой работает 100+ iOS разработчиков никто не следит за performance метриками и думаю этот вопрос поднимали и решали не раз, но требования, как известно, ставят не программисты.


        1. vitalybaev
          21.03.2017 23:26
          +1

          Никогда не судите работу таких крупных сервисов только по себе. У меня на 5ке работает идеально, а у жены на 7ке — вообще космос. Жор батарейки может случаться от миллиона причин и не все разработчики в принципе могут контролировать.
          В фейсбуке явно работают не дураки


          1. FirsofMaxim
            22.03.2017 05:13

            Это массовое явление к сожалению, https://www.dailydot.com/debug/restart-facebook-app-battery-drain/


      1. svistkovr
        21.03.2017 13:00

        К тому же я считаю, что размер приложения — далеко не показатель качества написания кода.


        Поставьте себя на место пользователя. Почему я должен скачивать очередное приложение более 100МБ и тратить свой трафик? При этом в приложении невозможно найти нужного функционала под кучей ненужного хлама.

        Если вы делаете приложение для пользователей, а не для менеджеров:
        — размер приложения должен быть минимален насколько это возможно (вы должны уважать трафик и время пользователя потраченые на ваше приложение)

        — открытость приложения (убрать все ненужные элементы и сделать явным самый необходимый функционал)

        Только пользователь будет оценивать вашу работу, не менеджеры и не другие программисты. Если работаете за зарплату и на удобства пользователей вам плевать — то смысл было писать эту статью?

        Я думаю, что очень многое продиктовано требованиями продукта. Думаю только одни кастомные эмоджи на экране лайков — 20-30 классов.


        Вы откройте приложение Facebook и посмотрите сколько реально экранов вы там можете найти, в коде может присутствовать скрытый функционал.
        Сравните с приложениями из других социальных сетей.
        Собрал статистику с пользовательского девайса по наиболее известным приложениям, например:
        Vkontakte 14 МБ
        Instagram 49 МБ
        TechMedia(приложение от хабра) 52МБ
        Steam 30МБ
        Telegram 35МБ
        Facebook (last update) 176 МБ


        1. PavelGatilov
          21.03.2017 13:14

          Поставьте себя на место пользователя. Почему я должен скачивать очередное приложение более 100МБ и тратить свой трафик? При этом в приложении невозможно найти нужного функционала под кучей ненужного хлама.

          Опять таки, не вижу никакой связи между юзабилити приложения и качеством кода. С другой стороны я прекрасно вижу зависимость между юзабилити и качеством продукта. Если это то, что вы имели ввиду — тогда я с вами согласен.

          Если вы делаете приложение для пользователей, а не для менеджеров:
          — размер приложения должен быть минимален насколько это возможно (вы должны уважать трафик и время пользователя потраченые на ваше приложение)

          Почему вы решили, что размер Facebook не минимален или не стремиться к минимальному размеру? Почему вы решили, что нет уважения трафика и времени пользователя?
          Я думаю, что 99% решений в Facebook, абсолютно не зависят от разработчиков. Многое продиктовано требованиями продукта и иногда просто невозможно сделать «быстрее, легче и меньше» по поставленным требованиям.

          — открытость приложения (убрать все ненужные элементы и сделать явным самый необходимый функционал)

          Опять таки, как это относится к качеству кода? К качеству UX — да, к качеству кода — нет.

          Если работаете за зарплату и на удобства пользователей вам плевать — то смысл было писать эту статью?

          И где я говорил, что мне плевать на удобства пользователей?

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

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

          Сравните с приложениями из других социальных сетей.

          И?

          TechMedia(приложение от хабра) 52МБ
          В десятки раз меньше по функционалу чем Facebook, а по размеру всего в 3.5.
          Steam 30МБ
          В основном одна большая web-view. Половина экранов — не нативные.
          Instagram 49 МБ
          Часть facebook. Принципы работы одни и теже.

          Вы откройте приложение Facebook и посмотрите сколько реально экранов вы там можете найти, в коде может присутствовать скрытый функционал.

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


  1. saniaxxx
    21.03.2017 12:45

    Вы говорите что

    Весь мусор такой как анимации, layout, композиции view, изменение отрисовок
    нужно вынести из контроллера, вы имеете в виду вынести в UIView? Или может быть сделать из UIViewController view а для контроллера создать отдельный класс?


    1. PavelGatilov
      21.03.2017 12:50

      Это уже как у вас принято на проекте или как удобнее разработчику.
      Можно выносить в отдельную UIView, можно написать extension на ViewController, можно создать отдельный объект который будет выполнять весь лайаут для конкретной UIView, можно, если нравится UIBuilder оставить весь лайаут в xib/storyboard.

      Или может быть сделать из UIViewController view а для контроллера создать отдельный класс?

      Многие так и делают, но статья была не об этом. Лично я не особо вижу смысл в создании view из UIViewController, ведь уже есть UIView на уровне выше.


  1. t-nick
    21.03.2017 12:50

    UIViewController — это такой же объект как и все остальные, и что у него должна быть только одна ответственность — связывать model и view.

    Однако, если мы посмотрим на интерфейс класса UIViewController, мы увидим, что Apple уже наделила его ответственностью — управлять циклом жизни своего view и взаимодействовать с другими view controller'ами.
    Добавлять в него ответственность связывания model с view считаю в корне не правильным (несмотря на то, что пишет Apple в гайдлайнах). Потому эту ответственность нужно выносить в отдельный класс — presenter (или controller). В случае с MVVM эта ответственность лежит на data binding механизме.

    Делить один экран на множество view controller'ов в большенстве случаев избыточно, так как нам не всегда нужна ленивая подгрузка view и прочие фичи UIViewController. Потому можно обойтись обычными сабвью со своими presenter/contoller'ами.


    1. PavelGatilov
      21.03.2017 12:58

      управлять циклом жизни своего view

      Этот механизм, на мой взгляд, и создан для обновления UIView в зависимости от состояния model при помощи controller'а и обратно.

      взаимодействовать с другими view controller'ами.

      При этом никто не заставляет вас писать весь этот код внутри контроллера. Более того, я считаю, что отдельно взятый контроллер ничего не должен знать о других контроллерах. И все взаимодействие должно быть инкапсулировано от контроллера.

      Добавлять в него ответственность связывания model с view считаю в корне не правильным (несмотря на то, что пишет Apple в гайдлайнах).

      Было бы интересно услышать аргументацию в поддержку этого мнения.

      Потому эту ответственность нужно выносить в отдельный класс — presenter (или controller). В случае с MVVM эта ответственность лежит на data binding механизме.

      В рамках других архитектур, таких как MVVM, VIPER, Flux и др, абсолютно с вами согласен. Но, если ваш проект написан с использованием MVC, я думаю, controller как раз и должен выполнять цикл обновления model-view.

      Делить один экран на множество view controller'ов в большенстве случаев избыточно, так как нам не всегда нужна ленивая подгрузка view и прочие фичи UIViewController. Потому можно обойтись обычными сабвью со своими presenter/contoller'ами.

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


      1. t-nick
        21.03.2017 13:26

        Этот механизм, на мой взгляд, и создан для обновления UIView в зависимости от состояния model при помощи controller'а и обратно.

        Как бы да, так говорит нам Apple в документации на UIViewController. Но принцип единой ответственности говорит о другом. Кроме того в интерфейсе UIViewController нет ни намека на наличие у него модели.

        Было бы интересно услышать аргументацию в поддержку этого мнения.

        Аргументация — SRP. Более того, один экран может иметь несколько слабо связанных элементов, каждый такой элемент должен контролироваться отдельным контроллером (презентером). Это и есть путь избавления от massive view controller.

        Разделение на childViewController делается не ради подгрузки, а ради гибкости, которую дает композиция.

        Если нам не нужно реагировать на события жизненного цикла вью (viewWillAppear: и т.п.) или взаимодействия с другими вью конироллерами (willMoveToParentViewController: и т.п.), то можно обойтись набором UIView. Гибкость та же. Например UITextView — наследник UIView, а не UIViewController, хотя логики там будь здоров.

        Однако с дочерними вью контроллерами удобнее работать в storyboard.


        1. PavelGatilov
          21.03.2017 13:34

          Но принцип единой ответственности говорит о другом

          В чем ответственность UIViewController тогда в данном случае?

          Кроме того в интерфейсе UIViewController нет ни намека на наличие у него модели

          Это потому, что по идее ViewController может использовать различные модели, или различные типы моделей. Поэтому реализация взаимодействия модели и контроллера лежит на разработчике.

          Аргументация — SRP.

          Хорошо, и что за responsibility?

          Более того, один экран может иметь несколько слабо связанных элементов, каждый такой элемент должен контролироваться отдельным контроллером (презентером)

          Если нам не нужно реагировать на события жизненного цикла вью (viewWillAppear: и т.п.) или взаимодействия с другими вью конироллерами (willMoveToParentViewController: и т.п.), то можно обойтись набором UIView.


          Т.е. вы сами себе немного противоречите? Вы говорите, что разбиение на слабо связанные элементы управляемые контроллерами и в то же время говорите, что разбиение на контроллеры избыточно и можно обходиться только UIView.

          каждый такой элемент должен контролироваться отдельным контроллером (презентером). Это и есть путь избавления от massive view controller.

          Если перечитаете пункт 3 из статьи — то вы как раз можете найти теже самые подходы.

          Например UITextView — наследник UIView, а не UIViewController, хотя логики там будь здоров.

          И во многих случаях, я считаю, имеет смысл создавать контроллер, который будет управлять логикой UITextView, для того чтобы не выносить эту логику в общие контроллеры.


          1. t-nick
            21.03.2017 13:46

            Вы очень невнимательно читаете мои комментарии, похоже.

            Хорошо, и что за responsibility?

            В 3-й раз: управлять циклом жизни своего view и взаимодействовать с другими view controller'ами, управлять дочерними вью контроллерами — показывать и прятать (как это делает UITabBarController), реагировать на storyboard segue. Не находите, что это уже включает достаточно много ответственности и достаточно раздутый интерфейс (привет ISP)?

            Т.е. вы сами себе немного противоречите? Вы говорите, что разбиение на слабо связанные элементы управляемые контроллерами и в то же время говорите, что разбиение на контроллеры избыточно и можно обходиться только UIView.

            Нет, не противоречу. Я разделяю наследников UIViewController и контроллеры/презентеры MVC/MVP. Избыточно разделение на UIViewController наследников. Можно обходиться набором UIView, каждая управляется своим контроллером (не UIViewController).

            И во многих случаях, я считаю, имеет смысл создавать контроллер, который будет управлять логикой UITextView, для того чтобы не выносить эту логику в общие контроллеры.

            Но контроллер вовсе не обязательно должен наследоваться от UIViewController.


            1. PavelGatilov
              21.03.2017 13:53

              Вы очень невнимательно читаете мои комментарии, похоже.

              Перечитывал дважды)
              Возможно это прорехи невербального контакта, иногда люди просто не так понимают друг друга при переписке.

              В 3-й раз: управлять циклом жизни своего view и взаимодействовать с другими view controller'ами, управлять дочерними вью контроллерами — показывать и прятать

              Хорошо, далее вопрос, что входит в таком случае в управление циклом жизни своего view?
              Показывать и прятать дочерние VC — хорошо, основываясь на чем? На изменении состояния модели?

              Нет, не противоречу. Я разделяю наследников UIViewController и контроллеры/презентеры MVC/MVP.

              С этого нужно было начать, вы нечетко выразили свои мысли. Статья абсолютно не об этом. Статья о том как сделать непосредственно наследников UIViewController легче, не используя альтернативные подходы такие как MVP, а лишь используя MVC предоставленный от Apple.

              Но контроллер вовсе не обязательно должен наследоваться от UIViewController

              Я вас понял, вы просто имеете ввиду презентеры из MVP или аналогичные сущности. Если посмотрите вначале статьи я упоминал, что такие подходы — абсолютно валидные варианты избавления от накопления ненужных зависимостей внутри VC. А все что было написано ниже относиться к «классическому» MVC от apple и к классическим VC наследникам UIViewController.
              Теперь вы поняли, что я имел ввиду?


              1. t-nick
                21.03.2017 14:02

                Хорошо, далее вопрос, что входит в таком случае в управление циклом жизни своего view?
                Показывать и прятать дочерние VC — хорошо, основываясь на чем? На изменении состояния модели?

                Обычно у вью контроллера есть свое внутреннее состояние, например selectedIndex у UITabBarController, еще он является делегатом UITabBar. Можно и модель, но она должна быть очень простой сущностью (не доменная модель).

                Теперь вы поняли, что я имел ввиду?

                Да, я вас понял. Надеюсь и вы меня ;)


  1. t-nick
    21.03.2017 12:50

    Главный недостаток storyboard — это невозможность внедрять внешние зависимости (что можно делать в nib/xib). Чтобы пробросить зависимость в сцену в глубине навигационного стека, приходится добавлять свойство в промежуточные view controller'ы, что нарушает принципы SOLID и делает код очень негибким. Другой подход — повсеместное использование синглтонов, что делает код не тестируемым.


    1. PavelGatilov
      21.03.2017 13:00

      У storyboard есть еще десяток фатальных недостатков.
      Статья не агитирует использовать storyboard, а лишь приводит некоторые рекомендации по разгрузке VC и связанных с ним storyboard.