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

Typhoon Explained

Typhoon Explained

Slides for Mobius Conference 2016.

Egor Tolstoy

June 04, 2016
Tweet

More Decks by Egor Tolstoy

Other Decks in Technology

Transcript

  1. T
    yphoon
    explained
    Egor T
    olstoy @igrekde

    View Slide

  2. 2

    View Slide

  3. 3

    View Slide

  4. 4
    Creating
    new project

    View Slide

  5. 5

    View Slide

  6. 6

    View Slide

  7. 7

    View Slide

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

    View Slide

  9. 9
    BarberService

    View Slide

  10. 10
    BarberService
    FakeBarberService

    View Slide

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

    View Slide

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

    View Slide

  13. 13

    BarberServiceMain
    BarberServiceFake

    View Slide

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

    View Slide

  15. 15

    BarberServiceMain
    Assembly
    содержат
    создает
    создает
    VC 3
    VC 4
    VC 5

    View Slide

  16. 16

    FakeBarberService
    Assembly
    содержат
    создает
    создает
    VC 3
    VC 4
    VC 5

    View Slide

  17. Assembly
    Typhoon

    View Slide

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

    View Slide

  19. 19
    Under the
    Hood

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  23. 23
    [BarberServiceMain new]
    [NetworkClient new]
    [BarberParser new]
    [BarberViewController new]
    [storyboard instantiateViewController:]

    View Slide

  24. 24
    Property
    Injection

    View Slide

  25. 25
    BarberServiceMain

    View Slide

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

    View Slide

  27. 27
    @implementation BarberListAssembly
    - (BarberListViewController *)barberListViewControllerDefinition {
    return [TyphoonDefinition withClass:[BarberListViewController class]
    configuration:^(TyphoonDefinition *definition) {
    [definition injectProperty:@selector(service)
    with:[self barberService]];
    }];
    }
    - (id)barberServiceMainDefinition {
    return [TyphoonDefinition withClass:[BarberServiceMain class]];
    }
    @end

    View Slide

  28. 28
    Modularizing
    Assemblies

    View Slide

  29. 29
    BarberServiceMain
    BarberServiceMain

    View Slide

  30. 30
    BarberListViewController
    BarberService
    BarberListAssembly
    BarberMapViewController
    BarberService
    BarberMapAssembly
    BarberService
    ServiceAssembly

    View Slide

  31. 31
    @interface BarberListAssembly
    @property (nonatomic, strong) TyphoonAssembly *serviceAssembly;
    @end
    @implementation BarberListAssembly
    - (BarberListViewController *)barberListViewControllerDefinition {
    return [TyphoonDefinition withClass:[BarberListViewController class]
    configuration:^(TyphoonDefinition *definition) {
    [definition injectProperty:@selector(service)
    with:[self.serviceAssembly
    barberService]];
    }];
    }
    @end

    View Slide

  32. 32
    Scopes

    View Slide

  33. 33
    LocationServiceMain
    CLLocationManager

    View Slide

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

    View Slide

  35. 35
    TyphoonScopeObjectGraph
    TyphoonScopePrototype
    TyphoonScopeSingleton
    TyphoonScopeLazySingleton
    TyphoonScopeWeakSingleton

    View Slide

  36. 36
    @implementation ServiceAssembly
    - (id)barberServiceMainDefinition {
    return [TyphoonDefinition withClass:[BarberServiceMain class]
    configuration:^(TyphoonDefinition *definition) {
    definition.scope = TyphoonScopeSingleton;
    }];
    }
    @end

    View Slide

  37. 37
    UI Injections

    View Slide

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

    View Slide

  39. 39
    JiggleAnimator
    Calculator1
    Calculator2

    View Slide

  40. 40

    View Slide

  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

    View Slide

  42. 42
    Method
    Injection

    View Slide

  43. 43
    MoustacheManager

    View Slide

  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

    View Slide

  45. 45
    Factories,
    attributes,
    options

    View Slide

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

    View Slide

  47. 47

    BarberServiceMoscow
    BarberServicePiter
    ServiceAssembly
    Москва
    Питер

    View Slide

  48. 48

    BarberServiceMoscow
    BarberServicePiter
    ServiceAssembly
    Москва
    Питер

    View Slide

  49. 49

    BarberServiceMoscow
    BarberServicePiter
    ServiceAssembly

    View Slide

  50. 50
    @interface BarberListAssembly
    @property (nonatomic, strong) TyphoonAssembly *serviceAssembly;
    @end
    @implementation BarberListAssembly
    - (BarberListViewController *)barberListViewControllerDefinition {
    return [TyphoonDefinition withClass:[BarberListViewController class]
    configuration:^(TyphoonDefinition *definition) {
    [definition injectProperty:@selector(factory)
    with:[self.serviceAssembly]];
    }];
    }
    @end

    View Slide

  51. 51
    @implementation ServiceAssembly
    - (id)barberServiceForCity:(NSString *)city {
    return [TyphoonDefinition withOption:city
    matcher:^(TyphoonOptionMatcher *matcher) {
    [matcher caseEqual:@"Moscow"
    use:[self moscowBarberService]];
    [matcher caseEqual:@"Piter"
    use:[self piterBarberService]];
    }];
    }
    @end

    View Slide

  52. 52
    [matcher caseEqual:@"Moscow"
    use:[self moscowBarberService]];
    [matcher caseEqual:@"Piter"
    use:[self piterBarberService]];

    View Slide

  53. 53
    Config

    View Slide

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

    View Slide

  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

    View Slide

  56. 56
    NSURL(http://mobiusconf.ru)
    MyStyle(#8732A9;17;HelveticeNeue-Regular)

    View Slide

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

    View Slide

  58. 58
    Instance
    Postprocessor

    View Slide

  59. 59

    View Slide

  60. 60
    BarberListRouter

    -openScreenWithIdentifier:(NSString *)identifier

    View Slide

  61. 61
    RouterDecorator
    BarberListRouter
    Flurry/Google

    identifier
    identifier

    View Slide

  62. 62
    @implementation AnalyticsPostProcessor
    - (id)postProcessInstance:(id)instance {
    if ([instance conformsToProtocol:@protocol(Router)]) {
    return [DecoratedRouter decoratedRouterWith:instance];
    }
    return instance;
    }
    @end

    View Slide

  63. 63
    Integration
    T
    esting

    View Slide

  64. 64
    BarberServiceMain

    NetworkClientMain

    View Slide

  65. 65
    BarberServiceMain

    NetworkClientFake

    View Slide

  66. 66
    BarberListViewController
    BarberService
    BarberListAssembly
    BarberService
    ServiceAssembly
    NetworkClient
    NetworkClientMain
    NetworkAssembly

    View Slide

  67. 67
    BarberListViewController
    BarberService
    BarberListAssembly
    BarberService
    ServiceAssembly
    NetworkClient
    NetworkClientFake
    NetworkAssembly

    View Slide

  68. 68
    - (void)setUp {
    ...
    TyphoonPatcher *patcher = [[TyphoonPatcher alloc] init];
    [patcher patchDefinitionWithSelector:@selector(networkClient)
    withObject:^id{
    return [NetworkClientFake new];
    }];
    [barberListAssembly attachPostProcessor:patcher];
    }

    View Slide

  69. 69
    Autowiring

    View Slide

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

    View Slide

  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];
    }

    View Slide

  72. 72
    Assembly
    Unit T
    ests

    View Slide

  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];
    }

    View Slide

  74. 74
    https://github.com/rambler-ios/
    RamblerTyphoonUtils

    View Slide

  75. 75
    Legends

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  81. 81
    Finally

    View Slide

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

    View Slide

  83. Egor T
    olstoy @igrekde
    Any magic, sufficiently analyzed is
    indistinguishable from technology
    [email protected]

    View Slide