Pull to refresh

Comments 21

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

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

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

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

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

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

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

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

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

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

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

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

Десятка экранов? Вы же это не серйозно.
К тому же я считаю, что размер приложения — далеко не показатель качества написания кода.
Более того, вот развернутый реверс их iOS App
Я думаю, что очень многое продиктовано требованиями продукта. Думаю только одни кастомные эмоджи на экране лайков — 20-30 классов.
И да, я считаю, что у многих спецов из Facebook есть чему поучится.
Насчет Facebook, я удалил его с моего iPhone5s (сейчас хожу через Хром в телефоне), жрал 35% батарейки, не уверен — относится это к качеству?
Тоже не уверен. Без знания бизнес требований к продукту очень сложно судить по единичным параметрам. Вполне могу себе представить ситуацию, когда требования от PO или BA были что-то вроде: «Нужно отправлять геолокацию на сервер каждые 15 секунд, это нужно для аналитики» или «нужно обрабатывать граф друзей при каждой загрузке фида для отправки нового запроса на рекомендации в друзья» и т. д.
Опять таки, не думаю, что в компании в которой работает 100+ iOS разработчиков никто не следит за performance метриками и думаю этот вопрос поднимали и решали не раз, но требования, как известно, ставят не программисты.
Никогда не судите работу таких крупных сервисов только по себе. У меня на 5ке работает идеально, а у жены на 7ке — вообще космос. Жор батарейки может случаться от миллиона причин и не все разработчики в принципе могут контролировать.
В фейсбуке явно работают не дураки
Это массовое явление к сожалению, https://www.dailydot.com/debug/restart-facebook-app-battery-drain/
К тому же я считаю, что размер приложения — далеко не показатель качества написания кода.


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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

И?

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

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

Не отрицаю, что в приложении очень много скрытого и возможно не совсем легального функционала, опять таки вы действительно думаете, что это имеет какое-то отношение к разработчикам?
Вы говорите что
Весь мусор такой как анимации, layout, композиции view, изменение отрисовок
нужно вынести из контроллера, вы имеете в виду вынести в UIView? Или может быть сделать из UIViewController view а для контроллера создать отдельный класс?
Это уже как у вас принято на проекте или как удобнее разработчику.
Можно выносить в отдельную UIView, можно написать extension на ViewController, можно создать отдельный объект который будет выполнять весь лайаут для конкретной UIView, можно, если нравится UIBuilder оставить весь лайаут в xib/storyboard.

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

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

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

Делить один экран на множество view controller'ов в большенстве случаев избыточно, так как нам не всегда нужна ленивая подгрузка view и прочие фичи UIViewController. Потому можно обойтись обычными сабвью со своими presenter/contoller'ами.
управлять циклом жизни своего 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 получает излишние зависимости и информацию о внешней среде.
Этот механизм, на мой взгляд, и создан для обновления UIView в зависимости от состояния model при помощи controller'а и обратно.

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Да, я вас понял. Надеюсь и вы меня ;)
Главный недостаток storyboard — это невозможность внедрять внешние зависимости (что можно делать в nib/xib). Чтобы пробросить зависимость в сцену в глубине навигационного стека, приходится добавлять свойство в промежуточные view controller'ы, что нарушает принципы SOLID и делает код очень негибким. Другой подход — повсеместное использование синглтонов, что делает код не тестируемым.
У storyboard есть еще десяток фатальных недостатков.
Статья не агитирует использовать storyboard, а лишь приводит некоторые рекомендации по разгрузке VC и связанных с ним storyboard.
Sign up to leave a comment.

Articles