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

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

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

Например, меня интересовал вопрос «что делать, если часть кода из одного 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 и AsyncDisplayKit. Также Александр, поведал, что в целях оптимизации, имеет смысл отказаться от autolayout и делать layout самому. Естественно, это нужно делать, думая головой, а не чем придется (никакого хардкода!). Грамотная реализация данного принципа может быть обнаружена в github.com/plasmLC/PPlayer. Также Александр порекомендовал не использовать CollectionView без веской необходимости.

Справедливости ради, считаю нужным сказать, что доклады от Sally Shpeard «Developing forApple TV», Brigit Lyons «Authentic testing for soundcloud», Chris Eidhof «Swift-like APIs» также были очень содержательными и полезными.

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

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


  1. bartleby
    18.11.2015 07:48

    А видео докладов будет?


    1. krokhmalyuk
      18.11.2015 08:20
      +1

      Уже: mbltdev.ru.


  1. progn
    18.11.2015 12:08

    По поводу autolayouts, есть конкретные примеры вот тут с ними лагает, а вот тут тоже самое, но отказались от автолайаутов считаем фреймы руками и все стало летать? И девайсы, версии ОС где это проявляется.

    «Components Kit и Async UI Kit» это про что? имеется ввиду AsyncDisplayKit от Фейсбука или что-то иное?


    1. Naftic
      18.11.2015 12:57

      Async UI Kit — имеется ввиду AsyncDisplayKit от фейсбука.

      По поводу, autolayouts — споры бесконечны. Но плюсов от них меньше чем минусов, судя по моему опыту.


      1. progn
        18.11.2015 13:29

        ну вот и хочется конкретики, а не споров.


        1. Naftic
          18.11.2015 13:55

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

          Пост от Александра Орлова — habrahabr.ru/post/264817. Пока ничего более путного, чем то, что было в докладе — не встречал.

          Также см. github.com/plasmLC/PPlayer (по рекомендации Алексндра).


          1. progn
            18.11.2015 13:58

            круто, спасибо!


            1. plasm
              18.11.2015 16:40

              Autolayout ужасно тормозная вещь. В докладе есть цифры, можно посмотреть запись на mbltdev.ru

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


              1. IgorFedorchuk
                18.11.2015 18:23

                Можно лейаут расчитывать один раз для всех ячеек перед reloadData с использованием Autolayout. И все тоже прекрасно летает. А расчет ручного лейаута — сущий ад. И правильно упоминалось в докладе, что тормоза хорошо проявляются при большом количетве ячеек. Если их до сотни, то вряд ли можно ощутить существенную разницу.


                1. plasm
                  18.11.2015 18:28

                  Зависит еще от огромного количества факторов. Ручной layout — вполне ок штука, и используется во многих крупных проектах(Telegram, VK, Facebook), потому что IB и Autolayout — днище.


                  1. IgorFedorchuk
                    18.11.2015 18:33

                    Ну это на холивар становится похоже. Есть просто огромная куча проектов, где используют IB и Autolayout и все прекрасно работает.


                    1. plasm
                      18.11.2015 18:35

                      Я приводил цифры, согласно которым очевидно, что нормально работать не будет. Если все прекрасно работает на последних устройствах и элементарным интерфейсом при 30-40 фпс — это не нормально.


                      1. IgorFedorchuk
                        18.11.2015 18:40

                        Надо еще привести цифры по времени на поддержку и написания ручного layout. На счет фпс — надо мерять и смотреть. В большинстве случаев неоправданно писать ручной layout. Хотя скайпу с его тормозами он бы явно не помешал.


                        1. plasm
                          18.11.2015 18:44

                          Секундочку, причем тут время разработки? Речь шла об оптимизации работы UITableView. Скорость разработки с ручным layout у меня и у Вас будет разная, тут ничего толком не померять.

                          Касательно FPS и скорости работы всё уже измерено — посмотрите доклад. (может позже будет нормальная отдельная запись)


                          1. IgorFedorchuk
                            18.11.2015 18:46

                            Согласен с тем, что с ручным layout будет работать быстрее. Доклад видел, статью читал. Ремарка была по поводу поддержки кода, стоит ли овчинка выделки?!


                            1. plasm
                              18.11.2015 18:48
                              +1

                              А, ну так зависит от проекта. Поэтому я не только про AL говорил.


                              1. IgorFedorchuk
                                18.11.2015 18:49

                                Вот и пришли к консенсусу.