Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Typhoon Explained

Typhoon Explained

Slides for Mobius Conference 2016.

Faf4a633b0d1e32a07a071039686c868?s=128

Egor Tolstoy

June 04, 2016
Tweet

Transcript

  1. T yphoon explained Egor T olstoy @igrekde

  2. 2

  3. 3

  4. 4 Creating new project

  5. 5

  6. 6

  7. 7

  8. 8 - loadBarbershops - cacheBarbershops - reloadTableData - loadBarbershops -

    cacheBarbershops - reloadTableData
  9. 9 BarberService

  10. 10 BarberService FakeBarberService

  11. 11 BarberService FakeBarberService VC 3 VC 4 VC 5 VC

    6
  12. 12 @interface BarberListViewController() @property (nonatomic, strong) BarberServiceMain *service; @end

  13. 13 <BarberService> BarberServiceMain BarberServiceFake

  14. 14 @interface BarberListViewController() @property (nonatomic, strong) id<BarberService> service; @end

  15. 15 <BarberService> BarberServiceMain Assembly содержат создает создает VC 3 VC

    4 VC 5
  16. 16 <BarberService> FakeBarberService Assembly содержат создает создает VC 3 VC

    4 VC 5
  17. Assembly Typhoon

  18. 18 Устройство Typhoon на трех пальцах Юзкейсы Легенды и мифы

  19. 19 Under the Hood

  20. 20 BarberViewController MapViewController BarberServiceMain BarberServiceFake Typhoon Component Factory componentForKey: Объект

  21. 21 BarberServiceMain type: (Class)BarberServiceMain key: barberServiceMainDefinition

  22. 22 BarberServiceMain type: (Class)BarberServiceMain key: barberServiceMainDefinition NetworkClient type: (Class)NetworkClient key:

    networkClientDefinition BarberParser type: (Class)BarberParser key: networkClientDefinition
  23. 23 [BarberServiceMain new] [NetworkClient new] [BarberParser new] [BarberViewController new] [storyboard

    instantiateViewController:]
  24. 24 Property Injection

  25. 25 <BarberService> BarberServiceMain

  26. 26 BarberListViewController type: (Class)BarberListViewController key: barberListViewControllerDefinition BarberService type: (Class)BarberServiceMain key:

    barberServiceMainDefinition BarberListAssembly
  27. 27 @implementation BarberListAssembly - (BarberListViewController *)barberListViewControllerDefinition { return [TyphoonDefinition withClass:[BarberListViewController

    class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(service) with:[self barberService]]; }]; } - (id<BarberService>)barberServiceMainDefinition { return [TyphoonDefinition withClass:[BarberServiceMain class]]; } @end
  28. 28 Modularizing Assemblies

  29. 29 <BarberService> BarberServiceMain <BarberService> BarberServiceMain

  30. 30 BarberListViewController BarberService BarberListAssembly BarberMapViewController BarberService BarberMapAssembly BarberService ServiceAssembly

  31. 31 @interface BarberListAssembly @property (nonatomic, strong) TyphoonAssembly<ServiceAssembly> *serviceAssembly; @end @implementation

    BarberListAssembly - (BarberListViewController *)barberListViewControllerDefinition { return [TyphoonDefinition withClass:[BarberListViewController class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(service) with:[self.serviceAssembly barberService]]; }]; } @end
  32. 32 Scopes

  33. 33 <LocationService> LocationServiceMain CLLocationManager

  34. 34 BarberListViewController LocationService BarberListAssembly BarberMapViewController LocationService BarberMapAssembly LocationService ServiceAssembly scope:

    TyphoonScopeSingleton
  35. 35 TyphoonScopeObjectGraph TyphoonScopePrototype TyphoonScopeSingleton TyphoonScopeLazySingleton TyphoonScopeWeakSingleton

  36. 36 @implementation ServiceAssembly - (id<BarberService>)barberServiceMainDefinition { return [TyphoonDefinition withClass:[BarberServiceMain class]

    configuration:^(TyphoonDefinition *definition) { definition.scope = TyphoonScopeSingleton; }]; } @end
  37. 37 UI Injections

  38. 38 BarberViewController MapViewController BarberServiceMain BarberServiceFake Typhoon Component Factory componentForClass: [BarberViewController

    class] [BarberViewController new]
  39. 39 JiggleAnimator Calculator1 Calculator2

  40. 40

  41. 41 @implementation ReusableViewAssembly - (MoustacheView *)moustacheView { return [TyphoonDefinition withClass:[MoustacheView

    class] configuration:^(TyphoonDefinition *definition) { [definition useInitializer:@selector(view)]; [definition injectProperty:[self animator]]; }]; } @end @implementation MoustacheView + (MoustacheView *)view { return [[[NSBundle mainBundle] loadNibNamed:@"MoustacheView"]; } @end
  42. 42 Method Injection

  43. 43 MoustacheManager

  44. 44 @implementation ReusableViewAssembly - (MoustacheView *)moustacheView { return [TyphoonDefinition withClass:[MoustacheView

    class] configuration:^(TyphoonDefinition *definition) { ... [definition injectProperty:[self manager]]; [definition injectMethod: @selector(subscribeToManager)]; }]; } @end @implementation MoustacheView - (void)subscribeToManager { [self.manager addMoustache:self]; } @end
  45. 45 Factories, attributes, options

  46. 46 Москва Питер

  47. 47 <ServiceFactory> BarberServiceMoscow BarberServicePiter ServiceAssembly Москва Питер

  48. 48 <ServiceFactory> BarberServiceMoscow BarberServicePiter ServiceAssembly Москва Питер

  49. 49 <ServiceFactory> BarberServiceMoscow BarberServicePiter ServiceAssembly

  50. 50 @interface BarberListAssembly @property (nonatomic, strong) TyphoonAssembly<ServiceAssembly> *serviceAssembly; @end @implementation

    BarberListAssembly - (BarberListViewController *)barberListViewControllerDefinition { return [TyphoonDefinition withClass:[BarberListViewController class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(factory) with:[self.serviceAssembly]]; }]; } @end
  51. 51 @implementation ServiceAssembly - (id<BarberService>)barberServiceForCity:(NSString *)city { return [TyphoonDefinition withOption:city

    matcher:^(TyphoonOptionMatcher *matcher) { [matcher caseEqual:@"Moscow" use:[self moscowBarberService]]; [matcher caseEqual:@"Piter" use:[self piterBarberService]]; }]; } @end
  52. 52 [matcher caseEqual:@"Moscow" use:[self moscowBarberService]]; [matcher caseEqual:@"Piter" use:[self piterBarberService]];

  53. 53 Config

  54. 54 AppDelegate TyphoonConfig(flurryKey) ApplicationAssembly TyphoonConfig(googleKey) { "config": { "flurryKey": "abcdef",

    "googleKey" : "ghijkl" } } config.plist
  55. 55 @implementation ApplicationAssembly - (AppDelegate *)appDelegate { return [TyphoonDefinition withClass:[AppDelegate

    class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(flurryKey) with:TyphoonConfig(@"config.flurryKey")]; [definition injectProperty:@selector(googleKey) with:TyphoonConfig(@"config.googleKey")]; }]; } @end
  56. 56 NSURL(http://mobiusconf.ru) MyStyle(#8732A9;17;HelveticeNeue-Regular)

  57. 57 PostCategories(top#cyr,0,cyr,cyr| top#noncyr,1,noncyr,noncyr)

  58. 58 Instance Postprocessor

  59. 59

  60. 60 BarberListRouter <Router> -openScreenWithIdentifier:(NSString *)identifier

  61. 61 RouterDecorator BarberListRouter Flurry/Google <Router> identifier identifier

  62. 62 @implementation AnalyticsPostProcessor - (id)postProcessInstance:(id)instance { if ([instance conformsToProtocol:@protocol(Router)]) {

    return [DecoratedRouter decoratedRouterWith:instance]; } return instance; } @end
  63. 63 Integration T esting

  64. 64 <BarberService> BarberServiceMain <NetworkClient> NetworkClientMain

  65. 65 <BarberService> BarberServiceMain <NetworkClient> NetworkClientFake

  66. 66 BarberListViewController BarberService BarberListAssembly BarberService ServiceAssembly NetworkClient NetworkClientMain NetworkAssembly

  67. 67 BarberListViewController BarberService BarberListAssembly BarberService ServiceAssembly NetworkClient NetworkClientFake NetworkAssembly

  68. 68 - (void)setUp { ... TyphoonPatcher *patcher = [[TyphoonPatcher alloc]

    init]; [patcher patchDefinitionWithSelector:@selector(networkClient) withObject:^id{ return [NetworkClientFake new]; }]; [barberListAssembly attachPostProcessor:patcher]; }
  69. 69 Autowiring

  70. 70 @interface BarberListViewControllerTests @property (nonatomic, strong) BarberListViewController *viewController; @property (nonatomic,

    strong) id<BarberService> service; @property (nonatomic, strong) MoustacheView *view; @end - (void)setUp { ... self.viewController = [barberListAssembly viewController]; self.service = [serviceAssembly barberService]; self.view = [moustacheViewAssembly moustacheView]; }
  71. 71 @interface BarberListViewControllerTests @property (nonatomic, strong) InjectedClass(BarberListViewController) viewController; @property (nonatomic,

    strong) InjectedProtocol(BarberService) service; @property (nonatomic, strong) InjectedClass(MoustacheView) view; @end - (void)setUp { ... [barberListAssembly inject:self]; }
  72. 72 Assembly Unit T ests

  73. 73 - (void)testThatAssemblyCreatesRouter { // given Class targetClass = [SettingsRouter

    class]; NSArray *dependencies = @[ RamblerSelector(transitionHandler) ]; // when id result = [self.assembly routerSettingsModule]; // then [self verifyTargetDependency:result withClass:targetClass dependencies:dependencies]; }
  74. 74 https://github.com/rambler-ios/ RamblerTyphoonUtils

  75. 75 Legends

  76. 76 Typhoon работает со Swift

  77. 77 Но… там же свиззлинг!

  78. 78 Высокий порог вхождения

  79. 79 Сильное влияние на отладку

  80. 80 Но я же могу велосипедить... %

  81. 81 Finally

  82. 82 Устройство Typhoon на трех пальцах Юзкейсы Легенды и мифы

  83. Egor T olstoy @igrekde Any magic, sufficiently analyzed is indistinguishable

    from technology igrekde@gmail.com