CocoaHeads Moscow. Владислав Дугнист. «Dependency Injection с Blood Magic»

Post on 21-Jan-2018

191 views 0 download

Transcript of CocoaHeads Moscow. Владислав Дугнист. «Dependency Injection с Blood Magic»

Dependency Injection в iOS

Дугнист Владислав

План

• Что такое зависимости?

• Что такое внедрение зависимостей (DI)?

• Какие плюсы мы получаем при использовании DI?

• Почему я выбрал Blood Magic.

2

Зависимости

View Controller

3

Зависимости

View Controller

Service

Data

3

Зависимости

- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [??? citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }

4

Зависимости

- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [??? citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }

Зависимость

4

Зависимости

Singleton решение: - (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [[WFCOpenWeatherService sharedInstance] citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }

5

Зависимости

Singleton решение: - (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [[WFCOpenWeatherService sharedInstance] citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }

Неявная зависимость

5

Признак неявных зависимостей

// WFCViewController.h

@interface WFCViewController : UIViewController

@end

6

Inversion of control// WFCViewController.h

@interface WFCViewController : UIViewController

@property (nonatomic) id <WFCWeatherServiceProtocol> weatherService;

@end

// WFCViewController.m

- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [_weatherService citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }

7

Чем полезен IoC?

• Повышает читаемость кода.

• Позволяет выставлять сервисы с заглушками в отладочной версии.

• Упрощает тестирование.

Демо

9

Blood Magic

• github: https://github.com/railsware/BloodMagic

• Podfile: pod 'BloodMagic/Injectable', :git => 'https://github.com/railsware/BloodMagic.git'

Blood Magic

BMInitializer *weatherServiceInitializer = [BMInitializer injectableInitializer];

weatherServiceInitializer.containerClass = [WFCViewController class];

weatherServiceInitializer.protocols =

@[@protocol(WFCWeatherServiceProtocol)];

weatherServiceInitializer.initializer = ^id (id sender) { return [WFCLocalWeatherService new]; }; [weatherServiceInitializer registerInitializer];

Blood Magic (синтаксис)

@interface BMInitializer : NSObject

@property (nonatomic, strong) Class propertyClass; @property (nonatomic, strong) Class containerClass; @property (nonatomic, strong) NSArray *protocols;

@property (nonatomic, copy) magic_initializer_t initializer;

- (void)registerInitializer;

@end

Blood Magic

// WFCViewController.h

@interface WFCViewController : UIViewController <BMInjectable>

@property (nonatomic) id <WFCWeatherServiceProtocol> weatherService;

@end

// WFCViewController.m

@dynamic weatherService;

Демо 2

Другие DI-фреймворки

Typhoon

• http://typhoonframework.org

• github: https://github.com/appsquickly/Typhoon

• Серия статей на хабре: http://habrahabr.ru/company/rambler-co/blog/258325/

• Доклад Rambler&Co: http://www.youtube.com/watch?v=LO59z3fjc9k

Typhoon

• Конфигурация зависимостей на уровне assembly.

• Auto-inject.

Typhoon

Удобные аннотации:

@interface WFCViewController : UIViewController

@property (nonatomic) InjectedProtocol(WFCWeatherServiceProtocol) weatherService;

@end

Typhoon@implementation WFCAssembly

- (id <WFCWeatherServiceProtocol>)defaultWeatherService { return [TyphoonDefinition withClass:[WFCLocalWeatherService class] configuration:^(TyphoonDefinition *definition) { definition.scope = TyphoonScopeSingleton; }]; }

@end

typedef NS_ENUM(NSInteger, TyphoonScope) { TyphoonScopeObjectGraph, TyphoonScopePrototype, TyphoonScopeSingleton, TyphoonScopeLazySingleton, TyphoonScopeWeakSingleton, };

Typhoon+ удобные аннотации

+ поддержка scope

+ больше community

- большие накладные расходы при работе с assembly

- нет возможности выставить условием containerClass при auto inject’ах

Objection

• http://objection-framework.org

• github: https://github.com/atomicobject/objection

Objection

@interface Car : NSObject { Engine *engine; Brakes *brakes; BOOL awake; }

// Will be filled in by objection @property(nonatomic, strong) Engine *engine; // Will be filled in by objection @property(nonatomic, strong) Brakes *brakes; @property(nonatomic) BOOL awake;

@implementation Car objection_requires(@"engine", @"brakes") @synthesize engine, brakes, awake; @end

Objection+ поддержка scope

+ второй по популярности после typhoon

- синтаксис

- отсутствие аннотаций

- нет возможности выставить условием containerClass при inject’ах

The end

cocoaheads slack: @dv

other: /vdugnist