Slides for Mobius Conference 2016.
TyphoonexplainedEgor Tolstoy @igrekde
View Slide
2
3
4Creatingnew project
5
6
7
8- loadBarbershops- cacheBarbershops- reloadTableData- loadBarbershops- cacheBarbershops- reloadTableData
9BarberService
10BarberServiceFakeBarberService
11BarberServiceFakeBarberServiceVC 3 VC 4VC 5VC 6
12@interface BarberListViewController()@property (nonatomic, strong) BarberServiceMain *service;@end
13BarberServiceMainBarberServiceFake
14@interface BarberListViewController()@property (nonatomic, strong) id service;@end
15BarberServiceMainAssemblyсодержатсоздаетсоздаетVC 3VC 4VC 5
16FakeBarberServiceAssemblyсодержатсоздаетсоздаетVC 3VC 4VC 5
AssemblyTyphoon
18Устройство Typhoon на трех пальцахЮзкейсыЛегенды и мифы
19Under theHood
20BarberViewControllerMapViewControllerBarberServiceMainBarberServiceFakeTyphoonComponentFactorycomponentForKey: Объект
21BarberServiceMaintype: (Class)BarberServiceMainkey: barberServiceMainDefinition
22BarberServiceMaintype: (Class)BarberServiceMainkey: barberServiceMainDefinitionNetworkClienttype: (Class)NetworkClientkey: networkClientDefinitionBarberParsertype: (Class)BarberParserkey: networkClientDefinition
23[BarberServiceMain new][NetworkClient new][BarberParser new][BarberViewController new][storyboard instantiateViewController:]
24PropertyInjection
25 BarberServiceMain
26BarberListViewControllertype: (Class)BarberListViewControllerkey: barberListViewControllerDefinitionBarberServicetype: (Class)BarberServiceMainkey: barberServiceMainDefinitionBarberListAssembly
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
28ModularizingAssemblies
29 BarberServiceMain BarberServiceMain
30BarberListViewControllerBarberServiceBarberListAssemblyBarberMapViewControllerBarberServiceBarberMapAssemblyBarberServiceServiceAssembly
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.serviceAssemblybarberService]];}];}@end
32Scopes
33 LocationServiceMainCLLocationManager
34BarberListViewControllerLocationServiceBarberListAssemblyBarberMapViewControllerLocationServiceBarberMapAssemblyLocationServiceServiceAssemblyscope: TyphoonScopeSingleton
35TyphoonScopeObjectGraphTyphoonScopePrototypeTyphoonScopeSingletonTyphoonScopeLazySingletonTyphoonScopeWeakSingleton
36@implementation ServiceAssembly- (id)barberServiceMainDefinition {return [TyphoonDefinition withClass:[BarberServiceMain class]configuration:^(TyphoonDefinition *definition) {definition.scope = TyphoonScopeSingleton;}];}@end
37UI Injections
38BarberViewControllerMapViewControllerBarberServiceMainBarberServiceFakeTyphoonComponentFactorycomponentForClass:[BarberViewController class] [BarberViewController new]
39JiggleAnimatorCalculator1Calculator2
40
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
42MethodInjection
43MoustacheManager
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
45Factories,attributes,options
46МоскваПитер
47BarberServiceMoscowBarberServicePiterServiceAssemblyМоскваПитер
48BarberServiceMoscowBarberServicePiterServiceAssemblyМоскваПитер
49BarberServiceMoscowBarberServicePiterServiceAssembly
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
51@implementation ServiceAssembly- (id)barberServiceForCity:(NSString *)city {return [TyphoonDefinition withOption:citymatcher:^(TyphoonOptionMatcher *matcher) {[matcher caseEqual:@"Moscow"use:[self moscowBarberService]];[matcher caseEqual:@"Piter"use:[self piterBarberService]];}];}@end
52[matcher caseEqual:@"Moscow"use:[self moscowBarberService]];[matcher caseEqual:@"Piter"use:[self piterBarberService]];
53Config
54AppDelegateTyphoonConfig(flurryKey)ApplicationAssemblyTyphoonConfig(googleKey){"config": {"flurryKey": "abcdef","googleKey" : "ghijkl"}}config.plist
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
56NSURL(http://mobiusconf.ru)MyStyle(#8732A9;17;HelveticeNeue-Regular)
57PostCategories(top#cyr,0,cyr,cyr|top#noncyr,1,noncyr,noncyr)
58InstancePostprocessor
59
60BarberListRouter-openScreenWithIdentifier:(NSString *)identifier
61RouterDecoratorBarberListRouterFlurry/Googleidentifieridentifier
62@implementation AnalyticsPostProcessor- (id)postProcessInstance:(id)instance {if ([instance conformsToProtocol:@protocol(Router)]) {return [DecoratedRouter decoratedRouterWith:instance];}return instance;}@end
63IntegrationTesting
64 BarberServiceMainNetworkClientMain
65 BarberServiceMainNetworkClientFake
66BarberListViewControllerBarberServiceBarberListAssemblyBarberServiceServiceAssemblyNetworkClientNetworkClientMainNetworkAssembly
67BarberListViewControllerBarberServiceBarberListAssemblyBarberServiceServiceAssemblyNetworkClientNetworkClientFakeNetworkAssembly
68- (void)setUp {...TyphoonPatcher *patcher = [[TyphoonPatcher alloc] init];[patcher patchDefinitionWithSelector:@selector(networkClient)withObject:^id{return [NetworkClientFake new];}];[barberListAssembly attachPostProcessor:patcher];}
69Autowiring
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];}
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];}
72AssemblyUnit Tests
73- (void)testThatAssemblyCreatesRouter {// givenClass targetClass = [SettingsRouter class];NSArray *dependencies = @[RamblerSelector(transitionHandler)];// whenid result = [self.assembly routerSettingsModule];// then[self verifyTargetDependency:resultwithClass:targetClassdependencies:dependencies];}
74https://github.com/rambler-ios/RamblerTyphoonUtils
75Legends
76Typhoon работает со Swift
77Но… там же свиззлинг!
78Высокий порог вхождения
79Сильное влияние на отладку
80Но я же могу велосипедить...%
81Finally
82Устройство Typhoon на трех пальцахЮзкейсыЛегенды и мифы
Egor Tolstoy @igrekdeAny magic, sufficiently analyzed isindistinguishable from technology[email protected]