Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Rambler.iOS #4: Создание модульных приложений на примере Рамблер.Кассы

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Создание модульных приложений
на примере
“Рамблер.Кассы”

YouTube-Videos werden auf SlideShare nicht mehr unterstützt.

Original auf YouTube ansehen

О чем?
• Введение в историю “Рамблер.Касса”
• Что используем
• Пример

Hier ansehen

1 von 65 Anzeige

Rambler.iOS #4: Создание модульных приложений на примере Рамблер.Кассы

Herunterladen, um offline zu lesen

Rambler.iOS #4: Rambler.iOS #4: Создание модульных приложений на примере Рамблер.Кассы (Савушкин Максим).

Rambler.iOS - митапы iOS-разработчиков, организуемые компанией RAMBLER&Co.

Rambler.iOS #4: Rambler.iOS #4: Создание модульных приложений на примере Рамблер.Кассы (Савушкин Максим).

Rambler.iOS - митапы iOS-разработчиков, организуемые компанией RAMBLER&Co.

Anzeige
Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Andere mochten auch (20)

Anzeige

Ähnlich wie Rambler.iOS #4: Создание модульных приложений на примере Рамблер.Кассы (20)

Weitere von RAMBLER&Co (13)

Anzeige

Aktuellste (20)

Rambler.iOS #4: Создание модульных приложений на примере Рамблер.Кассы

  1. 1. Создание модульных приложений на примере “Рамблер.Кассы”
  2. 2. О чем? • Введение в историю “Рамблер.Касса” • Что используем • Пример
  3. 3. О чем? • Введение в историю “Рамблер.Касса” • Что используем • Пример
  4. 4. О чем? • Введение в историю “Рамблер.Касса” • Что используем • Пример
  5. 5. Модуль — функционально законченный фрагмент программы, оформленный в виде отдельного файла с исходным кодом. Глоссарий
  6. 6. Модульность — это свойство системы, связанное с возможностью ее декомпозиции на ряд внутренне связанных между собой модулей Глоссарий
  7. 7. Немного истории • Приложение, отображающее информацию по событию: - кино - спектакли - спорт • Возможность купить билеты на эти события без наценки • iPhone и iPad версии Что же такое “Рамблер.Касса”?
  8. 8. Немного истории • Приложение, отображающее информацию по событию: - кино - спектакли - спорт • Возможность купить билеты на эти события без наценки • iPhone и iPad версии Что же такое “Рамблер.Касса”?
  9. 9. Немного истории • Приложение, отображающее информацию по событию: - кино - спектакли - спорт • Возможность купить билеты на эти события без наценки • iPhone и iPad версии Что же такое “Рамблер.Касса”?
  10. 10. Немного истории • Приложение, отображающее информацию по событию: - кино - спектакли - спорт • Возможность купить билеты на эти события без наценки • iPhone и iPad версии Что же такое “Рамблер.Касса”?
  11. 11. Немного истории Что же такое “Рамблер.Касса”?
  12. 12. Немного истории Что же такое “Рамблер.Касса”?
  13. 13. Немного истории • Проект развивается • Появляется первая “брендированная версия”
  14. 14. Немного истории Что же такое “брендированная” версия? • Отдельное приложение, существующее обособленно от основной версии • Имеет свои особенности: - своя цветовая схема, логотипы и т.д. - отличный от основной кассы функционал
  15. 15. Немного истории Что же такое “брендированная” версия?
  16. 16. Немного истории Что же такое “брендированная” версия?
  17. 17. Немного истории
  18. 18. • Общий функционал • Отличный функционал • Количество версий только растет Проблема
  19. 19. Проблема
  20. 20. Проблема
  21. 21. Расписание Поддержка Билеты Карта Спорт Кино Кино Кино Проблема Расписание Билеты Карта Расписание Поддержка Билеты
  22. 22. Как это было? • Один проект для всех версий • Множество таргетов • Ветвления через “if” по define макросам
  23. 23. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { #ifdef BOLSHOI switch (section) { case 2: return 2; case 3: return 2; default: return 0; } #else switch (section) { case 0: return 2; case 1: return 1; default: return 0; } #endif } Как это было?
  24. 24. - (instancetype)init { self = [super init]; NSString *bundleIdentifier = [[NSBundle mainBundle] infoDictionary][@"CFBundleIdentifier"]; if ([bundleIdentifier rangeOfString:@"cinemapark"].location != NSNotFound) { // CINEMA PARK _tintColor = [UIColor colorWithRed:31.f / 255.f green:110.f / 255.f blue:180.f / 255.f alpha:1.f]; _navigationBarTintColor = [UIColor colorWithRed:4.f/255.f green:110.f/255.f blue:180.f/255.f alpha:1.f]; _navigationBarTitleColor = [UIColor whiteColor]; _shouldShowTheaters = NO; _onlyOneCinema = NO; #if !defined(AF_APP_EXTENSIONS) [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; #endif if ([bundleIdentifier hasSuffix:@".dev"]) { _widgetKey = @"foo"; } else { _widgetKey = @"foo"; } } else if ([bundleIdentifier rangeOfString:@"Bolshoi"].location != NSNotFound) { // Bolshoi Rostov _tintColor = [UIColor kassaBolshoiMainColor]; _navigationBarTintColor = [UIColor kassaBolshoiMainColor]; _navigationBarTitleColor = [UIColor kassaBolshoiActiveTabsColor]; _selectedBarItemColor = [UIColor kassaBolshoiActiveTabsColor]; _unselectedBarItemColor = [UIColor kassaBolshoiSecondaryColor]; _barTextColor = [UIColor kassaBolshoiActiveTabsColor]; _shouldShowTheaters = NO; _onlyOneCinema = YES; if ([bundleIdentifier hasSuffix:@".dev"]) { _widgetKey = @"foo"; } else { _widgetKey = @"foo"; } }else { // KASSA APP _tintColor = [UIColor colorWithRed:255.f / 255.f green:133.f / 255.f blue:47.f / 255.f alpha:1.f]; _navigationBarTintColor = nil; _navigationBarTitleColor = nil; _selectedBarItemColor = _tintColor; _unselectedBarItemColor = nil; _barTextColor = nil; _shouldShowTheaters = YES; _onlyOneCinema = NO; if ([bundleIdentifier hasSuffix:@".dev"]) { _widgetKey = @"foo"; } else { _widgetKey = @"foo"; } } return self; } if ([bundleIdentifier rangeOfString:@"cinemapark"].location != NSNotFound) { // CINEMA PARK _tintColor = [UIColor colorWithRed:31.f / 255.f green:110.f / 255.f blue:180.f / 255.f alpha:1.f]; Как это было?
  25. 25. Как это было?
  26. 26. Решение • Модуль - экран приложения, выполняющий свою функцию • Саб-модуль - отдельная функциональность конкретного модуля, отвечающая за единственную обязанность
  27. 27. Решение
  28. 28. • Разбить приложение на модули • Разбить каждые модули на саб-модули • Подключать нужные модули, а с ними и нужные саб-модули для конкретных таргетов Решение
  29. 29. Решение Модуль “кинотеатры” • Получает через API список кинотеатров • Отображает этот список • Осуществляет навигацию на другие модули
  30. 30. Решение Модуль “кинотеатры” view presenter router interactor entity entity entity
  31. 31. Решение Модуль “кинотеатры” view presenter router interactor entityservice data source provider data source converter ui configurator
  32. 32. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  33. 33. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  34. 34. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  35. 35. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  36. 36. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  37. 37. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  38. 38. Nimbus Решение
  39. 39. Nimbus Cell Object Решение
  40. 40. Nimbus Cell Object Сконфигурированная ячейка Решение
  41. 41. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  42. 42. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  43. 43. TYPHOON Решение
  44. 44. Решение @interface RKCinemasDefaultConfiguratorAssembly : TyphoonAssembly @property (nonatomic, strong) RKSharedAssembly *sharedAssembly; - (id<RKCinemasViewProtocol, RKBaseListViewOutConfiguratorProtocol, RKCinemasDataProviderDelegate>)cinemasViewController; - (id<RKCinemasPresenterViewOutputProtocol, RKCinemasPresenterInteractorOutputProtocol>)cinemaPresenter; - (id<RKCinemasInteractorProtocol>)cinemasInteractor; - (id<RKCinemasRouterProtocol>)cinemasRouter; - (id<RKCinemasServiceProtocol>)cinemasService; - (id<RKBaseListViewConfiguratorProtocol>)cinemaConfigurator; - (id<RKCinemasDataSourceProviderProtocol>)cinemasDataSourceProvider; - (id<RKCinemasDataSourceConverterProtocol>)cinemasDataConverter; @end
  45. 45. Решение Активация фабрики
  46. 46. Решение
  47. 47. Решение
  48. 48. Решение Модуль “кинотеатры” view presenter router interactor entityservice data source provider data source converter ui configurator
  49. 49. view presenter router interactor entityservice data source provider data source converter ui configurator Решение Модуль “кинотеатры”
  50. 50. view presenter router interactor entityservice data source provider data source converter ui configurator RKCinemasDataConverter Решение Модуль “кинотеатры”
  51. 51. view presenter router interactor entityservice data source provider data source converter ui configurator RKCinemasDataConverter RKCinemasGiantDataConverter Решение Модуль “кинотеатры”
  52. 52. Решение @implementation RKCinemasDataConverter - (NSArray *)convertArrayOfListCinemasToPlaceCellObjects:(NSArray *)list { NSMutableArray *array = [[NSMutableArray alloc] init]; for (RKList *listObject in list) { [array addObject:listObject.title]; NSArray *objects = [self convertListOfCinemasToCellObjects:listObject.objects]; [array addObjectsFromArray:objects]; } return [array copy]; } - (NSArray *)convertListOfCinemasToCellObjects:(NSArray *)list { NSMutableArray *array = [[NSMutableArray alloc] init]; for (RKPlace *place in list) { [array addObject:[RKListPlaceCellObject objectWithPlace:place]]; } return [array copy]; } @end
  53. 53. Решение @implementation RKCinemasGiantDataConverter - (NSArray *)convertListOfCinemasToCellObjects:(NSArray *)list { NSMutableArray *array = [[NSMutableArray alloc] init]; for (RKPlace *place in list) { id<RKCinemaDataProtocol>cinemaInfo = [self.dataProvider cinemaInfoById:place.identifier]; NSString *backgroundImageName = [cinemaInfo backgroundImageName]; NSString *logoImageName = [cinemaInfo logoImageName]; [array addObject:[RKPhotoCinemaCellObject objectWithPlace:place backgroundImageName:backgroundImageName logoImageName:logoImageName]]; } return [array copy]; } - (NSArray *)convertArrayOfListCinemasToPlaceCellObjects:(NSArray *)list { NSMutableArray *array = [[NSMutableArray alloc] init]; for (RKList *listObject in list) { [array addObject:listObject.title]; NSArray *objects = [self convertListOfCinemasToCellObjects:listObject.objects]; [array addObjectsFromArray:objects]; } return [array copy]; } @end
  54. 54. Решение #import "RKCinemasDefaultConfiguratorAssembly.h" @protocol RKCinemasDataProviderProtocol; @interface RKCinemasGiantConfiguratorAssembly : RKCinemasDefaultConfiguratorAssembly - (id<RKCinemasDataSourceConverterProtocol>)cinemasDataConverter; - (id<RKCinemasDataProviderProtocol>)giantCinemasDataProvider; @end
  55. 55. Решение - (id<RKCinemasDataSourceConverterProtocol>)cinemasDataConverter { return [TyphoonDefinition withClass:[RKCinemasGiantDataConverter class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(dataProvider) with:[self giantCinemasDataProvider]]; }]; } - (id<RKCinemasDataSourceConverterProtocol>)cinemasDataConverter { return [TyphoonDefinition withClass:[RKCinemasDataConverter class]]; } Definition для основной версии Definition для “брединрованной” версии
  56. 56. Решение rambler-kassa.plist giant.plist
  57. 57. Решение
  58. 58. Заключение • Код чище • Уникальный функционал затрагивает только нужные таргеты • Общий код для всех таргетов • Тестирование саб-модулей
  59. 59. Заключение • Код чище • Уникальный функционал затрагивает только нужные таргеты • Общий код для всех таргетов • Тестирование саб-модулей
  60. 60. Заключение • Код чище • Уникальный функционал затрагивает только нужные таргеты • Общий код для всех таргетов • Тестирование саб-модулей
  61. 61. Заключение • Код чище • Уникальный функционал затрагивает только нужные таргеты • Общий код для всех таргетов • Тестирование саб-модулей
  62. 62. Заключение • VIPER • NIMBUS • TYPHOON
  63. 63. Заключение • COCOAPOD (?)
  64. 64. Ссылки http://typhoonframework.org/ Статья с общими принципами https://www.objc.io/issues/13-architecture/viper/ Официальный сайт проекта “Тyphoon” http://habrahabr.ru/company/rambler-co/blog/264683/ https://www.youtube.com/watch?v=LO59z3fjc9k TYPHOON Цикл статей от Егора Толстова Выступление на rambler.ios #3 VIPER https://medium.com/brigade-engineering/brigades-experience-using-an-mvc- alternative-36ef1601a41f Вводная статья NIMBUS https://github.com/jverkoey/nimbus Исходники и ссылка на wiki проекта http://www.slideshare.net/Rambler-iOS/nimbus-models Презентация с rambler.ios #1 от Стаса Цыганова

×