SlideShare una empresa de Scribd logo
1 de 27
Descargar para leer sin conexión
Александр Смирнов
Руководитель группы разработки, iOS Почта
alex.smirnov@corp.mail.ru
@__smirnov__
DEPENDENCY INJECTION
@__smirnov__
EVERY SOLUTION NEEDS A PROBLEM
@__smirnov__
ПРОБЛЕМЫ
@interface Emailer : NSObject {
@private
KlingonSpellChecker* spellChecker;
}
@end
@implementation Emailer
- (id)init {
if(self = [super init])
spellChecker = [KlingonSpellChecker new];
return self;
}
@end
• Связанный код
• Сложно переиспользовать
• Не тестируемый
• Зависимости скрыты
@__smirnov__
РЕШЕНИЯ ДО DEPENDENCY INJECTION
•Construction by hand
•Factory pattern
•ServiceLocator pattern
@__smirnov__
CONSTRUCTION BY HAND
@__smirnov__
CONSTRUCTION BY HAND
- (id)initWithSpellChecker:(id<SpellChecker>) spellChecker;
	

•	

 Нет сокрытия зависимостей
	

•	

 “Тестируемо”
	

•	

 Инъекция ‘руками’, нет
возможности сменить все и сразу
	

• Клиенты сервисов должны знать
как связаны графы объектов
- (id)init;
@__smirnov__
FACTORY PATTERN
@__smirnov__
FACTORY PATTERN
@interface EmailerFactory{}
- (id<Emailer>) createKlingonEmailer;
@end
+
- (id)initWithSpellChecker:(id<SpellChecker>) spellChecker;
@__smirnov__
@interface EmailerFactory{}
- (id<Emailer>) createKlingonEmailer;
@end
FACTORY PATTERN
• Нет сокрытия зависимостей
• “Тестируемо”
• Есть способ сменить все
зависимости разом
• Сами создаем объекты
• Больше сложных зависимостей
это более сложные фабрики
• Меняем код, чтобы тестировать
• По фабрике на каждый сервис ?
@__smirnov__
SERVICE LOCATOR PATTERN
[serviceLocator resolveByProtocol: @protocol(Emailer)];
[serviceLocator resolveByName: @"KlingonEmailer"];
@__smirnov__
SERVICE LOCATOR PATTERN
The key difference is that with a Service Locator every user of a
service has a dependency to the locator.The locator can hide
dependencies to other implementations, but you do need to see
the locator. (c) Martin Fowler
So the decision between locator and injector depends on whether that
dependency is a problem.
@__smirnov__
THE HOLLYWOOD PRINCIPLE
@__smirnov__
THE HOLLYWOOD PRINCIPLE
Don’t call us; we’ll call you
@__smirnov__
BIG DI BENEFITS
•Тестируемый код
•Переиспользуемый код
•Слабо связанный код
•!Scopes!
@__smirnov__
INJECTION IDIOMS
•Constructor injection
•Setter injection
•Interface injection
•Field injection
•Method injection (AOP)
NO IMAGE,
SORRY
@__smirnov__
CONSTRUCTOR INJECTION
Полностью готовый к работе объект
@interface SMTPEmailer<Emailer>
- (instancetype) initWithSpellchecker:(id<Spellchecker>) spellchecker
addressbook:(id<AddressBook>) addressbook;
@end
@interface EmailerClient: NSObject
- (instancetype) initWithEmailer:(id<Emailer>) emailer;
@end
@__smirnov__
SETTER INJECTION
@interface SMTPEmailer<Emailer>
@property(nonatomic, strong) id <Spellchecker> spellchecker;
@property(nonatomic, strong) id <AddressBook> addressbook;
@end
Можем модифицировать зависимости
Можем получить полусобранный объект
Можем намеренно не предоставлять часть зависимостей
@__smirnov__
METHOD INJECTION (AOP)
- (void) sendLetterWithSubject:(NSString*) subject
text:(NSString*) text {
NSLog(@"enter sendLetterWithSubject");
// do some real work
NSLog(@"exit sendLetterWithSubject");
}
@__smirnov__
BEYONDTHE SCOPE
• Singleton scope
• Transition objects, no scope
GENERAL PURPOSE SCOPES
• Request scope
• Session scope
• ...
APPLICATION LEVEL SCOPES
@__smirnov__
SINGLETON SCOPE
- (id) init {
return self = [super init];
}
- (void) doSomeWork {
[[Emailer sharedInstance] sendEmail];
}
- (id) initWithEmailer:(id<Emailer>) emailer {
if(self = [super init])
_emailer = emailer;
return self;
}
- (void) doSomeWork {
[_emailer sendEmail];
}
@__smirnov__
DOMAIN-SPECIFIC SCOPE
@interface SMTPEmailer<Emailer>
- (instancetype) initWithAccount:(Account*) account;
@end
@__smirnov__
IOS DEPENDENCY INJECTION
Мыши плакали, кололись, но все равно продолжали есть кактус
@__smirnov__
ALWAYS ALMOST GUICE
•“Annotation” Based Dependency
Injection
•Custom Object Providers
•Protocol Bindings
•Instance Bindings
•Lazily instantiates dependencies
Objection orTyphoon
•All above (except “annotation”)+
•!Autowiring!
•Assembling with blocks or XML
•AppCode integration
@__smirnov__
MATERIALS USED
• Inversion of Control Containers and the Dependency Injection
pattern by Martin Fowler
• Dependency Injection by Dhanji R. Prasanna ( author of Guice )
• Design Patterns: Dependency Injection by Griffin Caprio
( MSDN Magazine, September 2005 )
• Big Modular Java with Guice ( Google I/O 2009 )
• Dependency Injection ( !Wikipedia! )
@__smirnov__
@__smirnov__

Más contenido relacionado

Destacado (10)

Perepelitsa
PerepelitsaPerepelitsa
Perepelitsa
 
Rabovoluk
RabovolukRabovoluk
Rabovoluk
 
Zamyakin
ZamyakinZamyakin
Zamyakin
 
Haritonov
HaritonovHaritonov
Haritonov
 
Bubnov
BubnovBubnov
Bubnov
 
A.pleshkov
A.pleshkovA.pleshkov
A.pleshkov
 
Zagursky
ZagurskyZagursky
Zagursky
 
Osipov
OsipovOsipov
Osipov
 
Chudov
ChudovChudov
Chudov
 
Kubasov
KubasovKubasov
Kubasov
 

Más de kuchinskaya

владимир габриелян
владимир габриелянвладимир габриелян
владимир габриелянkuchinskaya
 
чашкин иван
чашкин иванчашкин иван
чашкин иванkuchinskaya
 
сумин андрей
сумин андрейсумин андрей
сумин андрейkuchinskaya
 
митасов роман
митасов романмитасов роман
митасов романkuchinskaya
 
кренин владимир
кренин владимиркренин владимир
кренин владимирkuchinskaya
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедевkuchinskaya
 
дыдыкин егор
дыдыкин егордыдыкин егор
дыдыкин егорkuchinskaya
 
ярослав рабоволюк
ярослав рабоволюкярослав рабоволюк
ярослав рабоволюкkuchinskaya
 
сергей спиридонов
сергей спиридоновсергей спиридонов
сергей спиридоновkuchinskaya
 
игорь ермаков
игорь ермаковигорь ермаков
игорь ермаковkuchinskaya
 
дмитрий юдин3
дмитрий юдин3дмитрий юдин3
дмитрий юдин3kuchinskaya
 

Más de kuchinskaya (12)

Kharkov
KharkovKharkov
Kharkov
 
владимир габриелян
владимир габриелянвладимир габриелян
владимир габриелян
 
чашкин иван
чашкин иванчашкин иван
чашкин иван
 
сумин андрей
сумин андрейсумин андрей
сумин андрей
 
митасов роман
митасов романмитасов роман
митасов роман
 
кренин владимир
кренин владимиркренин владимир
кренин владимир
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедев
 
дыдыкин егор
дыдыкин егордыдыкин егор
дыдыкин егор
 
ярослав рабоволюк
ярослав рабоволюкярослав рабоволюк
ярослав рабоволюк
 
сергей спиридонов
сергей спиридоновсергей спиридонов
сергей спиридонов
 
игорь ермаков
игорь ермаковигорь ермаков
игорь ермаков
 
дмитрий юдин3
дмитрий юдин3дмитрий юдин3
дмитрий юдин3
 

Smirnov dependency-injection-techforum(1)

  • 1.
  • 2. Александр Смирнов Руководитель группы разработки, iOS Почта alex.smirnov@corp.mail.ru @__smirnov__
  • 4. EVERY SOLUTION NEEDS A PROBLEM @__smirnov__
  • 5. ПРОБЛЕМЫ @interface Emailer : NSObject { @private KlingonSpellChecker* spellChecker; } @end @implementation Emailer - (id)init { if(self = [super init]) spellChecker = [KlingonSpellChecker new]; return self; } @end • Связанный код • Сложно переиспользовать • Не тестируемый • Зависимости скрыты @__smirnov__
  • 6. РЕШЕНИЯ ДО DEPENDENCY INJECTION •Construction by hand •Factory pattern •ServiceLocator pattern @__smirnov__
  • 8. CONSTRUCTION BY HAND - (id)initWithSpellChecker:(id<SpellChecker>) spellChecker; • Нет сокрытия зависимостей • “Тестируемо” • Инъекция ‘руками’, нет возможности сменить все и сразу • Клиенты сервисов должны знать как связаны графы объектов - (id)init; @__smirnov__
  • 10. FACTORY PATTERN @interface EmailerFactory{} - (id<Emailer>) createKlingonEmailer; @end + - (id)initWithSpellChecker:(id<SpellChecker>) spellChecker; @__smirnov__
  • 11. @interface EmailerFactory{} - (id<Emailer>) createKlingonEmailer; @end FACTORY PATTERN • Нет сокрытия зависимостей • “Тестируемо” • Есть способ сменить все зависимости разом • Сами создаем объекты • Больше сложных зависимостей это более сложные фабрики • Меняем код, чтобы тестировать • По фабрике на каждый сервис ? @__smirnov__
  • 12. SERVICE LOCATOR PATTERN [serviceLocator resolveByProtocol: @protocol(Emailer)]; [serviceLocator resolveByName: @"KlingonEmailer"]; @__smirnov__
  • 13. SERVICE LOCATOR PATTERN The key difference is that with a Service Locator every user of a service has a dependency to the locator.The locator can hide dependencies to other implementations, but you do need to see the locator. (c) Martin Fowler So the decision between locator and injector depends on whether that dependency is a problem. @__smirnov__
  • 15. THE HOLLYWOOD PRINCIPLE Don’t call us; we’ll call you @__smirnov__
  • 16. BIG DI BENEFITS •Тестируемый код •Переиспользуемый код •Слабо связанный код •!Scopes! @__smirnov__
  • 17. INJECTION IDIOMS •Constructor injection •Setter injection •Interface injection •Field injection •Method injection (AOP) NO IMAGE, SORRY @__smirnov__
  • 18. CONSTRUCTOR INJECTION Полностью готовый к работе объект @interface SMTPEmailer<Emailer> - (instancetype) initWithSpellchecker:(id<Spellchecker>) spellchecker addressbook:(id<AddressBook>) addressbook; @end @interface EmailerClient: NSObject - (instancetype) initWithEmailer:(id<Emailer>) emailer; @end @__smirnov__
  • 19. SETTER INJECTION @interface SMTPEmailer<Emailer> @property(nonatomic, strong) id <Spellchecker> spellchecker; @property(nonatomic, strong) id <AddressBook> addressbook; @end Можем модифицировать зависимости Можем получить полусобранный объект Можем намеренно не предоставлять часть зависимостей @__smirnov__
  • 20. METHOD INJECTION (AOP) - (void) sendLetterWithSubject:(NSString*) subject text:(NSString*) text { NSLog(@"enter sendLetterWithSubject"); // do some real work NSLog(@"exit sendLetterWithSubject"); } @__smirnov__
  • 21. BEYONDTHE SCOPE • Singleton scope • Transition objects, no scope GENERAL PURPOSE SCOPES • Request scope • Session scope • ... APPLICATION LEVEL SCOPES @__smirnov__
  • 22. SINGLETON SCOPE - (id) init { return self = [super init]; } - (void) doSomeWork { [[Emailer sharedInstance] sendEmail]; } - (id) initWithEmailer:(id<Emailer>) emailer { if(self = [super init]) _emailer = emailer; return self; } - (void) doSomeWork { [_emailer sendEmail]; } @__smirnov__
  • 23. DOMAIN-SPECIFIC SCOPE @interface SMTPEmailer<Emailer> - (instancetype) initWithAccount:(Account*) account; @end @__smirnov__
  • 24. IOS DEPENDENCY INJECTION Мыши плакали, кололись, но все равно продолжали есть кактус @__smirnov__
  • 25. ALWAYS ALMOST GUICE •“Annotation” Based Dependency Injection •Custom Object Providers •Protocol Bindings •Instance Bindings •Lazily instantiates dependencies Objection orTyphoon •All above (except “annotation”)+ •!Autowiring! •Assembling with blocks or XML •AppCode integration @__smirnov__
  • 26. MATERIALS USED • Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler • Dependency Injection by Dhanji R. Prasanna ( author of Guice ) • Design Patterns: Dependency Injection by Griffin Caprio ( MSDN Magazine, September 2005 ) • Big Modular Java with Guice ( Google I/O 2009 ) • Dependency Injection ( !Wikipedia! ) @__smirnov__