Первое впечатление об MBLTDev 2015

от автора

Первое впечатление об МБЛТ Дев 2015… пока еще не протрезвел от вискаря забыл все=)

Как iOS разработчик, признаюсь, что начало было немного скучным, но в целом, помимо докладов на выставке (конференции) было достаточно много интересных моментов. Особого внимания заслуживает упоминание прелестных сестричек из releadgion (спасибо за милые фотки!) и всех очаровательных представительниц прекрасной половины человечества, которые добавили в эту техническую ИТ конференцию щедрую порцию красоты.

А теперь о самих докладах. Опять же как iOS разработчика меня в первую очередь интересовали доклады о VIPER-е от Егора из Rambler&Co и «гладкие TableView» от Александра. Ребята не подвели — было очень круто. Давно уже изучаю этот паттерн и были несколько вопросов, которые стали для меня понятнее.

Например, меня интересовал вопрос «что делать если часть кода из одного Interactor-а нужно использовать в другом?». Ответ, очень прост — выделяем специальный слой services (где и будет весь reusable код).

Однако, не могу согласиться с тем, что для сервисов нужно использовать callback-функции, так как у callback-ов есть очень неприятный недостаток: если нужно в callback-е вызвать еще одну функцию с callback-ом, то возникает такая лапша:

[self someFunctionWithCallbackOnSucces:^{   [weakSelf anotherFunctionWithCallbackOnSucess:^{     // some code 1   } andFail:^{     // some code 1   }]; } andFail:^{   [weakSelf andTheOtherFunctionWithCallbackOnSucess:^{     // some code 2   } andFail:^{     // some code 2   }]; }]; 

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

Поясню. Как сказал, Егор в докладе «Секреты VIPER» — «Роутер должен роутить». Но проблема в том, что, например, в «эталонной» реализации VIPER By Jeff Gilbert and Conrad Stoll (статья на objc.io), упоминается некий wireframe, который:
1. создает все компоненты
2. конфигурирует зависимости (dependecy injection)
3. роутит

Что не очень согласуется с принципом Single Responsibilty. В рамблер, на сколько я понял, для используется следующая схема:
1. в storyboard-е мы задаем откуда куда переходить
2. в router-е мы перехватываем prepareForSegue и выполняем инициализацию
3. Typhoon делает Dependecy Injection

На мой, чисто субъективный, взгляд — это создает «ощущение правильности», но более «правильным» будет вынесение всех этих задач в явные классы. То есть:

@interface ModuleA_Router () <ModuleA_Router_Protocol> @property id<ModuleA_DependencyInjector> di;  @property id<ModueA_ViewFactory> viewFactory; @property id<ModuleA_InteractorFactory> interactorFactory; @property id<ModuleA_PresenterFactory> presenterFactory; @end  @implementation ModuleA_Router  - (void)showViewForModuleA {  // create   id view = [self.viewFactory createViewForModuleAWithParams:...];   id presenter = [self.presenterFactory createPresenterForModuleAWithParams:...];   id interactor = [self.interactorFactory createInteractorForModuleAWithParams:...];    // inject dependencies    [self.di configureModuleAWithView:view presenter:presenter interactor:interactor];    [self.navigationController pushViewController:view]; }  @end 

При таком подходе уже не важно какой тул используется для DI, а создание объектов полностью перенесено в factory-классы, которые мы собственно и тестим. Это не противоречит утверждению о том, что «каждый из терминов ‘View’, ‘Presenter’, ‘Interactor’ — это не конкретная сущность, а, скорей слой (который, в общем случае, может состоять из более чем одного класса)».

Еще один докладчик, а именно Kule Fuller, прояснил для меня вопрос о том, какими должны быть идеальные роутеры. В своем докладе он рассказывал, что весь transition у них представляет собой state machine. Что стало неким просветлением, для меня=)

Действительно, теперь можно код роутера представить более точно: нарисуем для себя логические переходы со скрина на скрин как конечный автомат, например, так:

 +--------------------+                                         +---------------------+   | state:             |   ----- {correct Login-Password} ---->  | state:              | | Authentication     |                                         | HomePage            | |                    |                                         |                     | +--------------------+                                         +---------------------+            | { wrong Login-Password }            |            | +---------------------+                                                           | state:              |    | Registration        |  |                     | +---------------------+ 

При этом, естественно, под конечным автоматом, понимать автомат с частичной функцией переходов (и, использование счетчиков в state-ах, для оптимизации). См. также state pattern от gang of four.

Кроме, того Егор и Rambler, представили миру много своих разработок, связанных с VIPER. Огромное спасибо!

Так, еще один доклад, который, на мой взгляд также достоен упоминания — это доклад об оптимизации TableView. К сожалению, сам доклад получился коротким и мы не успели задать вопросы, но в личной беседе мне все таки удалось узнать у Александра Орлова о различиях между Components Kit и Async UI Kit. Также Александр, поведал, что в целях оптимизации, имеет смысл отказаться от autolayout и делать layout самому. Естественно, это нужно делать думая головой, а не чем придется. Грамотная реализация данного принципа может быть обнаружена в github.com/plasmLC/PPlayer. Также Александр порекомендовал не использовать CollectionView без веской необходимости.

Спасибо организаторам за достойный «контекст» конференции и докладчикам за информативный день!

ссылка на оригинал статьи http://habrahabr.ru/post/271083/