SlideShare a Scribd company logo
1 of 36
ПРАКТИКА ИСПОЛЬЗОВАНИЯ
DEPENDENCY INJECTION
Виктор Петров, к.ф.-м.н, старший разработчик,
Сергей Анпилов, ведущий разработчик,
при участии команды разработки Kaspersky Endpoint Security for Windows
1
Из опыта разработки новой версии Kaspersky Endpoint
Security for Windows:
 Использование Service Locator. Подводные камни;
 Использование Dependency Injection. Подводные камни;
 Обзор современных C++ DI-фреймворков. Перспективы;
Содержание
2
Java/C# разработчик и Dependency Injection
C++ разработчик и Dependency Injection
C++ разработчик и Dependency Injection на C++11/14
3
Service Locator (SL) и Dependency Injection (DI) – способы реализации
инверсии управления (Inversion of Control, IoC)
class VirusDetector
{
shared_ptr<VirusBases> m_virusBases;
public:
VirusDetector()
{
m_virusBases = make_shared<VirusBases>();
}
...
};
Прямое управление
VirusDetectorC VirusBasesC
4
5
class VirusDetector
{
shared_ptr<IVirusBases> m_virusBases;
public:
explicit VirusDetector(
shared_ptr<IVirusBases> virusBases)
: m_virusBases(move(virusBases))
{
}
...
};
VirusDetectorC IVirusBasesI
VirusBasesC
6
Service Locator (SL) и Dependency Injection (DI) – способы реализации
инверсии управления (Inversion of Control, IoC)
Dependency Injection
7
VirusDetectorC
IVirusBasesI
VirusBasesC
class VirusDetector
{
shared_ptr<IVirusBases> m_virusBases;
public:
explicit VirusDetector(IServiceLocator* sl):
m_virusBases(sl->GetInterface(IID_OF(IVirusBases)))
{
}
...
};
IServiceLocatorI
ServiceLocatorC
8
Service Locator (SL) и Dependency Injection (DI) – способы реализации
инверсии управления (Inversion of Control, IoC)
Service Locator
9
Из опыта разработки новой версии Kaspersky Endpoint
Security for Windows:
 Использование Service Locator. Подводные камни;
 Использование Dependency Injection. Подводные камни;
 Обзор современных C++ DI-фреймворков. Перспективы;
Содержание
10
Components
AVP Seamless Update Service
AVP AVPSUS
Updater
Firewall
Antimalware
Antivirus
Driver
Scheduler
Message
Queue
11
Использование Service Locator в AVP
struct IServiceLocator : public IObject
{
virtual shared_ptr<IObject> GetInterface(iid_t iid) = 0;
};
struct IObjectFactory : public IObject
{
virtual shared_ptr<IObject> CreateInstance() = 0;
};
<component name="VirusBases" clsid="0xfe1fe107" module="virus_bases.dll">
<interface name="IVirusBases" iid="0x7996082a" />
</component>
shared_ptr<IObjectFactory> getObjectFactory(IServiceLocator*, clsid_t); // export
config
dll
source
12
AVP: получение списка зависимостей
Virus
Detector
GetInterface(IID_OF
(IVirusBasesN), basesN)
Service Locator Component Dependency Injection Component
class VirusDetector
{
public:
VirusDetector(
shared_ptr<IVirusBases1> bases1, ...,
shared_ptr<IVirusBasesM> basesM);
...
};
13
IDiskFormater* df
AVP: контроль используемых сервисов
Service Locator Component Dependency Injection Component
14
void UpdateBases(IServiceLocator* sl) {
...
OptimizeBasesFormat(sl);
}
void OptimizeBasesFormat(IServiceLocator* sl) {
}
// TODO: Defragment diskshared_ptr<IDiskFormater> diskFormater =
sl->GetInterface(IID_OF(IDiskFormater));
diskFormater->Format("C:");
df
void UpdateBases(
...
OptimizeBasesFormat(
}
) {
void OptimizeBasesFormat(
);
) {IDiskFormater* df
}
// TODO: Defragment diskdf->Format("C:");
AVP: unit-тестирование
Service Locator Component Dependency Injection Component
VirusDetectorC
IVirusBasesI
VirusBasesMockC
IServiceLocatorI
ServiceLocatorMockC
VirusDetectorC IVirusBasesI
VirusBasesMockC
См. также «получение списка зависимостей»15
DI в разных типах приложений
Service Locator Component Dependency Injection Component
SL
Application
DI
Application
Application
with SL of
another type
Non-IoC
Application
SL
Application
DI
Application
Application
with SL of
another type
Non-IoC
Application
Adapter
SL
component
DI
component
SL
component
SL
component
SL
component
Adapter Adapter
DI
component
DI
component
DI
component
16
AVPSUS: комбинирование DI и SL
template<typename T, typename... Deps>
shared_ptr<T> Adapter::CreateSLComponent(Deps... dependencies)
{
shared_ptr<IServiceLocator> sl = BuildServiceLocator(dependencies...);
shared_ptr<T> component = CreateObject<T>(sl);
return component;
}
DI application
Adapter SL component
17
Из опыта разработки новой версии Kaspersky Endpoint
Security for Windows:
 Использование Service Locator. Подводные камни;
 Использование Dependency Injection. Подводные
камни;
 Обзор современных C++ DI-фреймворков. Перспективы;
Содержание
18
AVPSUS: Подводные камни DI
1. Объекты создаются всегда, вне зависимости от частоты использования
19
class VirusDetector {
const shared_ptr<IVirusBases> m_virusBases;
const shared_ptr<IRecoveryManager> m_recoveryManager;
public:
VirusDetector(shared_ptr<IVirusBases> virusBases,
shared_ptr<IRecoveryManager> recoveryManager)
: m_virusBases(move(virusBases))
, m_recoveryManager(move(recoveryManager)) {}
void DetectViruses() {
try
{/* Detect */}
catch (const std::exception&)
{
m_recoveryManager->Recover();
}
}
};
2. Разрастание конструкторов - признак плохого дизайна.
class VirusDetector
{
public:
VirusDetector(IVirusBases* virusBases, IRecoveryManager* recoveryManager,
IAntimalwareDetector* antimalwareDetector, IAntiRootkitDetector*
antiRootkitDetector, IWebAnalyzer* webAnalyzer, IMailAnalyzer* mailAnalyzer,
ITrafficProcessor* trafficProcessor, IBasesDownloader* basesDownloader,
IBasesVerifier* basesVerifier, IWormsDetector* wormsDetector,
IVulnerabilityDetector* vulnerabilityDetector, ITrojanDetector* trojanDetector,
IStealthDetector* stealthDetector, ILicenseProvider* licenseProvider,
ISettingsProvider* settingsProvider, IPhishingDetector* phishingDetector,
IUrlFilter* urlFilter, IWoodPeckerDetector* woodPeckerDetector,
IMacroVirusesDetector* macroVirusesDetector, IAntiBanner* antiBanner,
ISystemWatcher* systemWatcher, IFileMonitor* fileMonitor, IRegistryMonitor*
registryMonitor, INetworkMonitor* networkMonitor, IApplcationMonitor*
applicationMonitor, IDeviceControl* deviceControl, IInstantMessengersMonitor*
instantMessengersMonitor);
/*...*/
};
20
AVPSUS: Подводные камни DI
3. Рост сложности конфигурации
void Configure()
{
auto vbFactory = CreateVirusBasesFactory();
auto vbConfig = LoadVirusBasesConfiguration();
auto virusBases = vbFactory->CreateVirusBases(vbConfig);
auto recoveryManager = TryCreateRecoveryManager();
if (!recoveryManager)
LogWarningRecoveryManagerNotAvailable();
auto amDetector = make_shared<AntimalwareDetector>(virusBases);
auto arDetector = make_shared<AntiRootkitDetector>(virusBases, amDetector);
auto webAnalyzer = make_shared<WebAnalyzer>(amDetector, recoveryManager);
auto mailAnalyzer = make_shared<MailAnalyzer>(amDetector, recoveryManager, webAnalyzer);
auto trafficProcessor = make_unique<TrafficProcessor>(arDetector, webAnalyzer, mailAnalyzer);
// ...
}
21
AVPSUS: Подводные камни DI
Из опыта разработки новой версии Kaspersky Endpoint
Security for Windows:
 Использование Service Locator. Подводные камни;
 Использование Dependency Injection. Подводные камни;
 Обзор современных C++ DI-фреймворков.
Перспективы;
Содержание
22
DI фреймворк: перспектива развития AVPSUS
DI фреймворк – средство конструирования объектов на основе
заданной конфигурации зависимостей.
Мотивация:
• Отделение конфигурации от логики;
• Декларативность описания конфигурации;
23
Технические требования:
• Простота конфигурирования компонентов;
• Явность списка зависимостей компонент;
• Обнаружение ошибок конфигурации на этапе компиляции;
• Отсутствие необходимости изменять код компонентов;
• Минимальные зависимости на этапах сборки и выполнения;
Общие требования:
• Лицензия допускает коммерческое использование;
• Прохождение апробации в крупных проектах;
• Активное развитие и поддержка проекта;
DI фреймворк: требования AVPSUS
24
[C++98] PocoCapsule
[Detector.xml]
<?xml version=”1.0”?>
<!DOCTYPE poco-application-context SYSTEM
“http://www.pocomatic.com/poco-application-
context.dtd”>
<poco-application-context>
<load library=“./virus_detector.$dll“/>
<load library=“./virus_detector_reflx.$dll“/>
<bean class=“IVirusBases“ factory-
method=“CreateVirusBases“/>
<bean
class=”VirusDetector”
id=”detector”
destroy-method=”delete”
lazy-init=”false”>
<method-arg ref=”IVirusBases”/>
<ioc method=”Init”>
<method-arg type=”cstring” value=”mode=fast”/>
</ioc>
</bean>
</poco-application-context>
[Detector.h]
struct IVirusBases {};
class VirusBases : public IVirusBases {};
IVirusBases* CreateVirusBases()
{ return new VirusBases(); }
class VirusDetector {
public:
explicit VirusDetector(IVirusBases*);
void Init(const char*);
void Detect();
};
25
[C++98] PocoCapsule
virus_detector_reflx.dll
virus_
detector.h
virus_
detector.xml
pxgenproxy
virus_
detector.cc
main.exe
main.cpp
pococapsule.dll
[main.cpp]
#include <pocoapp.h>
int main(int argc, char** argv)
{
POCO_AppContext* ctxt = POCO_AppContext::create(
“virus_detector.xml”, “file”);
VirusDetector* det = ctxt->getBean("detector");
det->Detect();
ctxt->terminate();
ctxt->destroy();
}
26
[C++03] Wallaroo
[virus_detector.h]
#include "wallaroo/registered.h"
struct IVirusBases : public wallaroo::Part {};
class VirusBases : public IVirusBases {};
class VirusDetector : public wallaroo::Part
{
wallaroo::Collaborator<IVirusBases>
m_virusBases;
public:
VirusDetector(IVirusBases* virusBases);
void Detect();
};
[virus_detector.cpp]
#include "virus_detector.h"
WALLAROO_REGISTER(IVirusBases)
WALLAROO_REGISTER(VirusBases)
WALLAROO_REGISTER(VirusDetector, IVirusBases*)
VirusDetector::VirusDetector()
: m_virusBases("m_virusBases", RegistrationToken())
{}
void VirusDetector::Detect() {}
27
int main(int argc, char* argv[]) {
try {
Catalog catalog;
catalog.Create("virusDetector", "VirusDetector");
catalog.Create("virusBases", "VirusBases");
use(catalog["virusBases"]).as("m_virusBases").of(catalog["virusDetector"]);
shared_ptr<VirusDetector> virusDetector = catalog["virusDetector"];
virusDetector->Detect();
}
catch (const wallaroo::WallarooError& error) {
std::cerr << "ERROR: " << error.what() << std::endl;
}
return 0;
}
[C++03] Wallaroo
28
[C++11] Google Fruit
class IVirusBases {
virtual void Check(string s) = 0;
};
class VirusBases : public IVirusBases {
public:
VirusBases() = default;
virtual void Check() override {
...
}
};
struct IVirusDetector {
virtual void Detect() = 0;
};
class VirusDetector : public
IVirusDetector {
shared_ptr<IVirusBases> m_bases;
public:
VirusDetector(const
shared_ptr<IVirusBases>& bases)
: m_bases(bases) {}
virtual void Detect() override {
m_bases->Check();
}
};
29
Component<IVirusDetector> getDetectorComponent()
{
return fruit::createComponent()
.registerConstructor<VirusDetector(IVirusBases*)>()
.registerConstructor<VirusBases()>()
.bind<IVirusBases, VirusBases>()
.bind<IVirusDetector, VirusDetector>();
}
int main() {
Injector<IVirusDetector>
injector(getDetectorComponent());
shared_ptr<IVirusDetector> detector =
injector.get<IVirusDetector*>();
detector->Detect();
return 0;
}
[C++11] Google Fruit
30
[C++03/11/14]Boost.DI
struct IVirusBases {
virtual void Check() = 0;
};
class VirusBases : public IVirusBases {…};
struct IAntimalware {
virtual void Scan() = 0;
};
class Antimalware : public IAntimalware
{...};
class VirusDetector{
shared_ptr<IVirusBases> m_virusBases;
shared_ptr<IAntimalware> m_antimalware;
bool m_value;
public:
VirusDetector(
const shared_ptr<IVirusBases>& virusBases,
const shared_ptr<IAntimalware>& antimalware,
bool value)
: m_virusBases(virusBases)
, m_antimalware(antimalware)
, m_value(value)
{ }
int Detect() const {
if (m_value) {
m_virusBases->Check();
m_antimalware->Scan();
}
return 0;
}
};31
int main() {
auto injector = di::make_injector(
di::bind<IVirusBases, VirusBases>
, di::bind<IAntimalware, Antimalware>
, di::bind<bool>.to(true)
);
return injector.create<VirusDetector>().Detect();
}
[C++03/11/14]Boost.DI
32
Poco
Capsule
Wallaroo
Google
Fruit
Boost.DI
manual
DI
Простота конфигурирования
компонентов
Да Да Да Да Нет
Явность списка зависимостей
компонент
Нет Нет Да Нет Да
Обнаружение ошибок конфигурации
на этапе компиляции
Нет Нет Да Да Да
Отсутствие необходимости изменять
код компонентов
Да Нет Да Да Да
Минимальные зависимости на
этапах сборки и выполнения
Нет Да Да Да Да
33
DI фреймворки: сравнение
Poco
Capsule
Wallaroo
Google
Fruit
Boost.DI
manual
DI
Лицензия допускает
коммерческое использование
LGPL Да Да Да Да
Прохождение апробации в
крупных проектах
Нет Нет Нет Нет Да
Активное развитие и поддержка
проекта
Нет Да Да Да Да
34
DI фреймворки: сравнение
DI в современном C++: выводы
• Dependency Injection предпочтительнее Service Locator для
связывания объектов;
• Для C++-проекта с инверсией зависимости на текущий момент
предпочтительнее использовать manual DI либо DI-фреймворк
собственной разработки для связывания объектов.
35
Ссылки
• http://www.martinfowler.com/articles/injection.html
• http://www.objectmentor.com/resources/articles/dip.pdf
• https://code.google.com/p/pococapsule/
• https://code.google.com/p/wallaroo/
• https://github.com/google/fruit
• https://github.com/krzysztof-jusiak/di
36

More Related Content

What's hot

Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016
Кирилл Толкачёв
 
"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013
"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013
"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013
Vladimir Ivanov
 

What's hot (20)

Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
 
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETЧто нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
 
Continuous Delivery with Jenkins: Lessons Learned
Continuous Delivery with Jenkins: Lessons LearnedContinuous Delivery with Jenkins: Lessons Learned
Continuous Delivery with Jenkins: Lessons Learned
 
Как за час сделать недельную работу
Как за час сделать недельную работуКак за час сделать недельную работу
Как за час сделать недельную работу
 
Самоорганизующаяся сервисная инфраструктура на базе Docker / Данила Штань (То...
Самоорганизующаяся сервисная инфраструктура на базе Docker / Данила Штань (То...Самоорганизующаяся сервисная инфраструктура на базе Docker / Данила Штань (То...
Самоорганизующаяся сервисная инфраструктура на базе Docker / Данила Штань (То...
 
Angular 2: Всех переиграл
Angular 2: Всех переигралAngular 2: Всех переиграл
Angular 2: Всех переиграл
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 
"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013
"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013
"Invokedynamic: роскошь или необходимость?"@ JavaOne Moscow 2013
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Модульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETМодульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NET
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 

Viewers also liked

SOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайнаSOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайна
Михаил Польгун
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by Example
Benjamin Eberlei
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Google
yaevents
 

Viewers also liked (10)

DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 
Как писать красивый код или основы SOLID
Как писать красивый код или основы SOLIDКак писать красивый код или основы SOLID
Как писать красивый код или основы SOLID
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHP
 
SOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайнаSOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайна
 
Василий Сорокин, “Google C++ Mocking and Test Frameworks”
Василий Сорокин, “Google C++ Mocking and Test Frameworks”Василий Сорокин, “Google C++ Mocking and Test Frameworks”
Василий Сорокин, “Google C++ Mocking and Test Frameworks”
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by Example
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Google
 
Павел Филонов, Разделяй и управляй вместе с Conan.io
Павел Филонов, Разделяй и управляй вместе с Conan.ioПавел Филонов, Разделяй и управляй вместе с Conan.io
Павел Филонов, Разделяй и управляй вместе с Conan.io
 
Practical unit testing in c & c++
Practical unit testing in c & c++Practical unit testing in c & c++
Practical unit testing in c & c++
 
Clean Unit Test Patterns
Clean Unit Test PatternsClean Unit Test Patterns
Clean Unit Test Patterns
 

Similar to Практика использования Dependency Injection

Непрерывная интеграция. Практическое применение
Непрерывная интеграция. Практическое применениеНепрерывная интеграция. Практическое применение
Непрерывная интеграция. Практическое применение
devclub
 
Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...
Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...
Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...
Cisco Russia
 
6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting
KewpaN
 
Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...
Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...
Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...
Ontico
 
Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...
Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...
Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...
IT Event
 

Similar to Практика использования Dependency Injection (20)

Программные интерфейсы управления (API) архитектурой, ориентированной на прил...
Программные интерфейсы управления (API) архитектурой, ориентированной на прил...Программные интерфейсы управления (API) архитектурой, ориентированной на прил...
Программные интерфейсы управления (API) архитектурой, ориентированной на прил...
 
Полная автоматизация развертываний ПО: общие концепции, пример реализации, ср...
Полная автоматизация развертываний ПО: общие концепции, пример реализации, ср...Полная автоматизация развертываний ПО: общие концепции, пример реализации, ср...
Полная автоматизация развертываний ПО: общие концепции, пример реализации, ср...
 
Непрерывная интеграция. Практическое применение
Непрерывная интеграция. Практическое применениеНепрерывная интеграция. Практическое применение
Непрерывная интеграция. Практическое применение
 
Web deployment
Web deploymentWeb deployment
Web deployment
 
CocoaHeads Moscow. Владислав Дугнист. «Dependency Injection с Blood Magic»
CocoaHeads Moscow. Владислав Дугнист. «Dependency Injection с Blood Magic»CocoaHeads Moscow. Владислав Дугнист. «Dependency Injection с Blood Magic»
CocoaHeads Moscow. Владислав Дугнист. «Dependency Injection с Blood Magic»
 
CONTINUOUS INTEGRATION ДЛЯ ЧАЙНИКОВ ВМЕСТЕ С TEAMCITY
CONTINUOUS INTEGRATION ДЛЯ ЧАЙНИКОВ ВМЕСТЕ С TEAMCITYCONTINUOUS INTEGRATION ДЛЯ ЧАЙНИКОВ ВМЕСТЕ С TEAMCITY
CONTINUOUS INTEGRATION ДЛЯ ЧАЙНИКОВ ВМЕСТЕ С TEAMCITY
 
Инновационное SDN решение для ЦОД Cisco ACI Anywhere
Инновационное SDN решение для ЦОД Cisco ACI AnywhereИнновационное SDN решение для ЦОД Cisco ACI Anywhere
Инновационное SDN решение для ЦОД Cisco ACI Anywhere
 
Взломать сайт на ASP.NET
Взломать сайт на ASP.NETВзломать сайт на ASP.NET
Взломать сайт на ASP.NET
 
Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...
Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...
Автоматизированое развертывание виртуализированной инфраструктуры с интегриро...
 
SECON'2017, Васин Вячеслав, Жизнь без SDL
SECON'2017, Васин Вячеслав, Жизнь без SDLSECON'2017, Васин Вячеслав, Жизнь без SDL
SECON'2017, Васин Вячеслав, Жизнь без SDL
 
Жизнь без SDL
Жизнь без SDLЖизнь без SDL
Жизнь без SDL
 
Методы выполнения требования 6.6 PCI DSS – практический выбор
Методы выполнения требования 6.6 PCI DSS – практический выборМетоды выполнения требования 6.6 PCI DSS – практический выбор
Методы выполнения требования 6.6 PCI DSS – практический выбор
 
Zend framework 2
Zend framework 2Zend framework 2
Zend framework 2
 
Внедрение зависимостей в ASP.NET MVС и ASP.NET vNext
Внедрение зависимостей в ASP.NET MVС и ASP.NET vNextВнедрение зависимостей в ASP.NET MVС и ASP.NET vNext
Внедрение зависимостей в ASP.NET MVС и ASP.NET vNext
 
Как это будет: ASP.NET Core
Как это будет: ASP.NET CoreКак это будет: ASP.NET Core
Как это будет: ASP.NET Core
 
HPI: Расширенные возможности и модели использования
HPI: Расширенные возможности и модели использованияHPI: Расширенные возможности и модели использования
HPI: Расширенные возможности и модели использования
 
Программируемость ACI. Примеры применения.
Программируемость ACI. Примеры применения.Программируемость ACI. Примеры применения.
Программируемость ACI. Примеры применения.
 
6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting6 создание распределенных приложений по технологии remoting
6 создание распределенных приложений по технологии remoting
 
Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...
Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...
Инфраструктура распределенных приложений на nodejs / Станислав Гуменюк (Rambl...
 
Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...
Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...
Александр Сычев "Статика и динамика. Как фреймворки помогут прокачать ваше пр...
 

More from Platonov Sergey

Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Platonov Sergey
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычислений
Platonov Sergey
 

More from Platonov Sergey (20)

Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практике
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутов
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++
 
C++ exceptions
C++ exceptionsC++ exceptions
C++ exceptions
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычислений
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим жить
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузера
 
Concepts lite
Concepts liteConcepts lite
Concepts lite
 

Практика использования Dependency Injection

  • 1. ПРАКТИКА ИСПОЛЬЗОВАНИЯ DEPENDENCY INJECTION Виктор Петров, к.ф.-м.н, старший разработчик, Сергей Анпилов, ведущий разработчик, при участии команды разработки Kaspersky Endpoint Security for Windows 1
  • 2. Из опыта разработки новой версии Kaspersky Endpoint Security for Windows:  Использование Service Locator. Подводные камни;  Использование Dependency Injection. Подводные камни;  Обзор современных C++ DI-фреймворков. Перспективы; Содержание 2
  • 3. Java/C# разработчик и Dependency Injection C++ разработчик и Dependency Injection C++ разработчик и Dependency Injection на C++11/14 3
  • 4. Service Locator (SL) и Dependency Injection (DI) – способы реализации инверсии управления (Inversion of Control, IoC) class VirusDetector { shared_ptr<VirusBases> m_virusBases; public: VirusDetector() { m_virusBases = make_shared<VirusBases>(); } ... }; Прямое управление VirusDetectorC VirusBasesC 4
  • 5. 5
  • 6. class VirusDetector { shared_ptr<IVirusBases> m_virusBases; public: explicit VirusDetector( shared_ptr<IVirusBases> virusBases) : m_virusBases(move(virusBases)) { } ... }; VirusDetectorC IVirusBasesI VirusBasesC 6 Service Locator (SL) и Dependency Injection (DI) – способы реализации инверсии управления (Inversion of Control, IoC) Dependency Injection
  • 7. 7
  • 8. VirusDetectorC IVirusBasesI VirusBasesC class VirusDetector { shared_ptr<IVirusBases> m_virusBases; public: explicit VirusDetector(IServiceLocator* sl): m_virusBases(sl->GetInterface(IID_OF(IVirusBases))) { } ... }; IServiceLocatorI ServiceLocatorC 8 Service Locator (SL) и Dependency Injection (DI) – способы реализации инверсии управления (Inversion of Control, IoC) Service Locator
  • 9. 9
  • 10. Из опыта разработки новой версии Kaspersky Endpoint Security for Windows:  Использование Service Locator. Подводные камни;  Использование Dependency Injection. Подводные камни;  Обзор современных C++ DI-фреймворков. Перспективы; Содержание 10
  • 11. Components AVP Seamless Update Service AVP AVPSUS Updater Firewall Antimalware Antivirus Driver Scheduler Message Queue 11
  • 12. Использование Service Locator в AVP struct IServiceLocator : public IObject { virtual shared_ptr<IObject> GetInterface(iid_t iid) = 0; }; struct IObjectFactory : public IObject { virtual shared_ptr<IObject> CreateInstance() = 0; }; <component name="VirusBases" clsid="0xfe1fe107" module="virus_bases.dll"> <interface name="IVirusBases" iid="0x7996082a" /> </component> shared_ptr<IObjectFactory> getObjectFactory(IServiceLocator*, clsid_t); // export config dll source 12
  • 13. AVP: получение списка зависимостей Virus Detector GetInterface(IID_OF (IVirusBasesN), basesN) Service Locator Component Dependency Injection Component class VirusDetector { public: VirusDetector( shared_ptr<IVirusBases1> bases1, ..., shared_ptr<IVirusBasesM> basesM); ... }; 13
  • 14. IDiskFormater* df AVP: контроль используемых сервисов Service Locator Component Dependency Injection Component 14 void UpdateBases(IServiceLocator* sl) { ... OptimizeBasesFormat(sl); } void OptimizeBasesFormat(IServiceLocator* sl) { } // TODO: Defragment diskshared_ptr<IDiskFormater> diskFormater = sl->GetInterface(IID_OF(IDiskFormater)); diskFormater->Format("C:"); df void UpdateBases( ... OptimizeBasesFormat( } ) { void OptimizeBasesFormat( ); ) {IDiskFormater* df } // TODO: Defragment diskdf->Format("C:");
  • 15. AVP: unit-тестирование Service Locator Component Dependency Injection Component VirusDetectorC IVirusBasesI VirusBasesMockC IServiceLocatorI ServiceLocatorMockC VirusDetectorC IVirusBasesI VirusBasesMockC См. также «получение списка зависимостей»15
  • 16. DI в разных типах приложений Service Locator Component Dependency Injection Component SL Application DI Application Application with SL of another type Non-IoC Application SL Application DI Application Application with SL of another type Non-IoC Application Adapter SL component DI component SL component SL component SL component Adapter Adapter DI component DI component DI component 16
  • 17. AVPSUS: комбинирование DI и SL template<typename T, typename... Deps> shared_ptr<T> Adapter::CreateSLComponent(Deps... dependencies) { shared_ptr<IServiceLocator> sl = BuildServiceLocator(dependencies...); shared_ptr<T> component = CreateObject<T>(sl); return component; } DI application Adapter SL component 17
  • 18. Из опыта разработки новой версии Kaspersky Endpoint Security for Windows:  Использование Service Locator. Подводные камни;  Использование Dependency Injection. Подводные камни;  Обзор современных C++ DI-фреймворков. Перспективы; Содержание 18
  • 19. AVPSUS: Подводные камни DI 1. Объекты создаются всегда, вне зависимости от частоты использования 19 class VirusDetector { const shared_ptr<IVirusBases> m_virusBases; const shared_ptr<IRecoveryManager> m_recoveryManager; public: VirusDetector(shared_ptr<IVirusBases> virusBases, shared_ptr<IRecoveryManager> recoveryManager) : m_virusBases(move(virusBases)) , m_recoveryManager(move(recoveryManager)) {} void DetectViruses() { try {/* Detect */} catch (const std::exception&) { m_recoveryManager->Recover(); } } };
  • 20. 2. Разрастание конструкторов - признак плохого дизайна. class VirusDetector { public: VirusDetector(IVirusBases* virusBases, IRecoveryManager* recoveryManager, IAntimalwareDetector* antimalwareDetector, IAntiRootkitDetector* antiRootkitDetector, IWebAnalyzer* webAnalyzer, IMailAnalyzer* mailAnalyzer, ITrafficProcessor* trafficProcessor, IBasesDownloader* basesDownloader, IBasesVerifier* basesVerifier, IWormsDetector* wormsDetector, IVulnerabilityDetector* vulnerabilityDetector, ITrojanDetector* trojanDetector, IStealthDetector* stealthDetector, ILicenseProvider* licenseProvider, ISettingsProvider* settingsProvider, IPhishingDetector* phishingDetector, IUrlFilter* urlFilter, IWoodPeckerDetector* woodPeckerDetector, IMacroVirusesDetector* macroVirusesDetector, IAntiBanner* antiBanner, ISystemWatcher* systemWatcher, IFileMonitor* fileMonitor, IRegistryMonitor* registryMonitor, INetworkMonitor* networkMonitor, IApplcationMonitor* applicationMonitor, IDeviceControl* deviceControl, IInstantMessengersMonitor* instantMessengersMonitor); /*...*/ }; 20 AVPSUS: Подводные камни DI
  • 21. 3. Рост сложности конфигурации void Configure() { auto vbFactory = CreateVirusBasesFactory(); auto vbConfig = LoadVirusBasesConfiguration(); auto virusBases = vbFactory->CreateVirusBases(vbConfig); auto recoveryManager = TryCreateRecoveryManager(); if (!recoveryManager) LogWarningRecoveryManagerNotAvailable(); auto amDetector = make_shared<AntimalwareDetector>(virusBases); auto arDetector = make_shared<AntiRootkitDetector>(virusBases, amDetector); auto webAnalyzer = make_shared<WebAnalyzer>(amDetector, recoveryManager); auto mailAnalyzer = make_shared<MailAnalyzer>(amDetector, recoveryManager, webAnalyzer); auto trafficProcessor = make_unique<TrafficProcessor>(arDetector, webAnalyzer, mailAnalyzer); // ... } 21 AVPSUS: Подводные камни DI
  • 22. Из опыта разработки новой версии Kaspersky Endpoint Security for Windows:  Использование Service Locator. Подводные камни;  Использование Dependency Injection. Подводные камни;  Обзор современных C++ DI-фреймворков. Перспективы; Содержание 22
  • 23. DI фреймворк: перспектива развития AVPSUS DI фреймворк – средство конструирования объектов на основе заданной конфигурации зависимостей. Мотивация: • Отделение конфигурации от логики; • Декларативность описания конфигурации; 23
  • 24. Технические требования: • Простота конфигурирования компонентов; • Явность списка зависимостей компонент; • Обнаружение ошибок конфигурации на этапе компиляции; • Отсутствие необходимости изменять код компонентов; • Минимальные зависимости на этапах сборки и выполнения; Общие требования: • Лицензия допускает коммерческое использование; • Прохождение апробации в крупных проектах; • Активное развитие и поддержка проекта; DI фреймворк: требования AVPSUS 24
  • 25. [C++98] PocoCapsule [Detector.xml] <?xml version=”1.0”?> <!DOCTYPE poco-application-context SYSTEM “http://www.pocomatic.com/poco-application- context.dtd”> <poco-application-context> <load library=“./virus_detector.$dll“/> <load library=“./virus_detector_reflx.$dll“/> <bean class=“IVirusBases“ factory- method=“CreateVirusBases“/> <bean class=”VirusDetector” id=”detector” destroy-method=”delete” lazy-init=”false”> <method-arg ref=”IVirusBases”/> <ioc method=”Init”> <method-arg type=”cstring” value=”mode=fast”/> </ioc> </bean> </poco-application-context> [Detector.h] struct IVirusBases {}; class VirusBases : public IVirusBases {}; IVirusBases* CreateVirusBases() { return new VirusBases(); } class VirusDetector { public: explicit VirusDetector(IVirusBases*); void Init(const char*); void Detect(); }; 25
  • 26. [C++98] PocoCapsule virus_detector_reflx.dll virus_ detector.h virus_ detector.xml pxgenproxy virus_ detector.cc main.exe main.cpp pococapsule.dll [main.cpp] #include <pocoapp.h> int main(int argc, char** argv) { POCO_AppContext* ctxt = POCO_AppContext::create( “virus_detector.xml”, “file”); VirusDetector* det = ctxt->getBean("detector"); det->Detect(); ctxt->terminate(); ctxt->destroy(); } 26
  • 27. [C++03] Wallaroo [virus_detector.h] #include "wallaroo/registered.h" struct IVirusBases : public wallaroo::Part {}; class VirusBases : public IVirusBases {}; class VirusDetector : public wallaroo::Part { wallaroo::Collaborator<IVirusBases> m_virusBases; public: VirusDetector(IVirusBases* virusBases); void Detect(); }; [virus_detector.cpp] #include "virus_detector.h" WALLAROO_REGISTER(IVirusBases) WALLAROO_REGISTER(VirusBases) WALLAROO_REGISTER(VirusDetector, IVirusBases*) VirusDetector::VirusDetector() : m_virusBases("m_virusBases", RegistrationToken()) {} void VirusDetector::Detect() {} 27
  • 28. int main(int argc, char* argv[]) { try { Catalog catalog; catalog.Create("virusDetector", "VirusDetector"); catalog.Create("virusBases", "VirusBases"); use(catalog["virusBases"]).as("m_virusBases").of(catalog["virusDetector"]); shared_ptr<VirusDetector> virusDetector = catalog["virusDetector"]; virusDetector->Detect(); } catch (const wallaroo::WallarooError& error) { std::cerr << "ERROR: " << error.what() << std::endl; } return 0; } [C++03] Wallaroo 28
  • 29. [C++11] Google Fruit class IVirusBases { virtual void Check(string s) = 0; }; class VirusBases : public IVirusBases { public: VirusBases() = default; virtual void Check() override { ... } }; struct IVirusDetector { virtual void Detect() = 0; }; class VirusDetector : public IVirusDetector { shared_ptr<IVirusBases> m_bases; public: VirusDetector(const shared_ptr<IVirusBases>& bases) : m_bases(bases) {} virtual void Detect() override { m_bases->Check(); } }; 29
  • 30. Component<IVirusDetector> getDetectorComponent() { return fruit::createComponent() .registerConstructor<VirusDetector(IVirusBases*)>() .registerConstructor<VirusBases()>() .bind<IVirusBases, VirusBases>() .bind<IVirusDetector, VirusDetector>(); } int main() { Injector<IVirusDetector> injector(getDetectorComponent()); shared_ptr<IVirusDetector> detector = injector.get<IVirusDetector*>(); detector->Detect(); return 0; } [C++11] Google Fruit 30
  • 31. [C++03/11/14]Boost.DI struct IVirusBases { virtual void Check() = 0; }; class VirusBases : public IVirusBases {…}; struct IAntimalware { virtual void Scan() = 0; }; class Antimalware : public IAntimalware {...}; class VirusDetector{ shared_ptr<IVirusBases> m_virusBases; shared_ptr<IAntimalware> m_antimalware; bool m_value; public: VirusDetector( const shared_ptr<IVirusBases>& virusBases, const shared_ptr<IAntimalware>& antimalware, bool value) : m_virusBases(virusBases) , m_antimalware(antimalware) , m_value(value) { } int Detect() const { if (m_value) { m_virusBases->Check(); m_antimalware->Scan(); } return 0; } };31
  • 32. int main() { auto injector = di::make_injector( di::bind<IVirusBases, VirusBases> , di::bind<IAntimalware, Antimalware> , di::bind<bool>.to(true) ); return injector.create<VirusDetector>().Detect(); } [C++03/11/14]Boost.DI 32
  • 33. Poco Capsule Wallaroo Google Fruit Boost.DI manual DI Простота конфигурирования компонентов Да Да Да Да Нет Явность списка зависимостей компонент Нет Нет Да Нет Да Обнаружение ошибок конфигурации на этапе компиляции Нет Нет Да Да Да Отсутствие необходимости изменять код компонентов Да Нет Да Да Да Минимальные зависимости на этапах сборки и выполнения Нет Да Да Да Да 33 DI фреймворки: сравнение
  • 34. Poco Capsule Wallaroo Google Fruit Boost.DI manual DI Лицензия допускает коммерческое использование LGPL Да Да Да Да Прохождение апробации в крупных проектах Нет Нет Нет Нет Да Активное развитие и поддержка проекта Нет Да Да Да Да 34 DI фреймворки: сравнение
  • 35. DI в современном C++: выводы • Dependency Injection предпочтительнее Service Locator для связывания объектов; • Для C++-проекта с инверсией зависимости на текущий момент предпочтительнее использовать manual DI либо DI-фреймворк собственной разработки для связывания объектов. 35
  • 36. Ссылки • http://www.martinfowler.com/articles/injection.html • http://www.objectmentor.com/resources/articles/dip.pdf • https://code.google.com/p/pococapsule/ • https://code.google.com/p/wallaroo/ • https://github.com/google/fruit • https://github.com/krzysztof-jusiak/di 36

Editor's Notes

  1. (Сергей) Представление (Сергей) Незримо команда КЕС (Сергей) Рад приветствовать
  2. (Сергей) Опыт из разработки KES (Enterprise) (Сергей) КЕС – большой проект – компоненты – инверсия управления – как у нас – SL&DI – плюс-минус-ПК (Сергей) Развитие как DI Framework – обзор – применимость по нашему опыту – перспективы C++11/14
  3. (Сергей) джава в зале (Сергей) большинство в зале (Сергей) C++11/14 – заинтересовать, посмотреть под новым углом (Сергей) Хватит воды, код, Витя
  4. Поясним понятия DI, SL и IoC на примере. При традиционном подходе компонент создает конкретную реализацию
  5. Аналогия Это проблема потому что добавление функцмональности требует изменения отлаженного, оттестированного кода
  6. Вместо зависимости от конкретной реализации – от интерфейса в конструкторе. Таким образом VirusDetector начал управлять, а не зависеть
  7. Вставляем сервмсы от которых зависит и только их
  8. Альтернатива – SL Компоненты как нужные, так и не нужные Это удобно (на все случаи жизни), компонента по-прежнему зависит от интерфейса, а не от реализации
  9. Возвращаясь к аналогии
  10. Описанные подходы мы использовали при разработке новой версии Endpoint Securit Задача – сделать внешний модуль обновления для антивируса (DI). При этом использовали существующие компонент (SL)
  11. SL представлен в продукте интерфейсом c методом Который по id интерфейса -> имя модуля и id класса-реализации В модуле вызывает статический метод для создания фабрики, с помощью которой создается требуемая реализация
  12. Посмотрим с какими проблемами использования SL побудили использовать DI При переносе существующей SL-компоненты (т.е. Комопоненты, использующей SL в реализации) в новое окружение требуется получить список зависимых сервисов SL – поиск и отсмотр всех вхождений DI – список получается явно из параметров конструктора
  13. В случае SL сложно контролировать список Например, если в процессе эволюции повторно используемого компонента появилась новая зависимость, это будет скрыто от пользователя SL-компоненты и очевидно пользователю DI-компоненты
  14. Еще одна проблема SL – усложнение юнит-тестирования. Нужен дополнительный mock-объект. В то же время наш опыт показал, что эта сложность переоценена. Гораздо больше юнит-тестирование усложняется ранее озвученной сложностью получения списка зависимостей;
  15. Еще одной проблемой SL является его навязчивость, т.е. при использовании SL-компоненты необходимо использовать и SL, а в случае его отсутствия реализовывать адаптер. DI компоненту же можно использовать без дополнительных сложностей. Надо отметить, что в нашей ситуации выбора между SL & DI при разработке нового приложения данный минус SL являлся аргументом за то чтобы продолжить его использование.
  16. Таким образом, мы пришли к выводу что для нового приложения AVPSUS предпочтительнее использовать DI. При этом нам потребовалось для каждой SL-компоненты создавать индивидуальный адаптер сервис-локатора и наполнять его теми и только теми сервисами, от которых зависит данный конкретный комопнент.
  17. (Сергей) Рассмотрели шишки AVP. Перенесемся во времени, рассмотрим шишки AVPSUS. И тут не все гладко. (Сергей) Один из минусов – отсутствие бесплатного ленивого создания; (Сергей) Можно обойти с помощью дополнительных фабрик, но это дополнительная работа; (Сергей) По нашему опыту не так часто важно, минус не существеннен;
  18. (Сергей) Другой проблемой считается разрастание (Сергей) Было на AVPSUS, думали беда (Сергей) Подумали лучше, поняли что проблема в дизайне (Сергей) 1. Много зависимостей (Сергей) 2. Ненужное пробрасывание зависимостей, частичная реализация DI (Сергей) Сделали рефакторинг. Миф разрушен
  19. (Сергей) Наконец реальная проблема (Сергей) Нельзя вечно зависеть от абстракции, есть конкретика – в конфигурации (Сергей) Большому проекту большая конфигурация. 1000 строк (Сергей) Разложенный в линию граф. Трудно вручную вносить изменения
  20. (Сергей) DI не панацея. Существует класс решений. Что такое ДИ фреймворк? (Сергей) DI фреймворки предоставляют возможность декларативно описывать конфигурацию, отделив ее от повторно используемой логики. В идеале это позволит создавать различные продукты из готовых компонент, изменяя лишь конфигурацию
  21. (Сергей) Сформулируем требования (Сергей) В первую очередь решать задачу (Сергей) Конечно, при этом не хотим регресс (список, раннее обнаружение ошибок) (Сергей) Большая кодовая база – не хотим менять код (Сергей) Желательно упростить внедрение, минимум зависимостей (Сергей) Помимо этого требования общего вида (Сергей) Конечно, лицензия (Сергей) Проверенность временем и индустрией. Активная Поддержка авторами (Сергей) Надо отметить что требования специфичны AVPSUS. По сути нам нужно решение для DI на уровне объектов. На более высоком уровне (пример AVP) требования иные. Возможны даже комбинации решений. (Сергей) Давайте рассмотрим /* Сформулируем требования, которым должен удовлетворять DI фрейфорк, чтобы мы могли его применить в AVPSUS. В первую очередь он должен упрощать конфигурацию. При этом нам важно не потерять преимуществ DI над Sl, а именно явного списка зависимостей компонентов и раннего обнаружения ошибок. С учетом большой кодовой базы мы не можем себе позволить использовать фреймворк, требующий изменений в коде компонент. Желательно минимизировать зависимости фреймворка для упрощения процесса внедрения. Помимо технических есть ряд требований общего характера: лицензия должна позволять использовать фреймформ */
  22. Зависимости описываются конфигурационным xml-файлом; Поддержка вызовов методов после инициализации
  23. Двухэтапный цикл сборки: – Усложняет процесс работы; + Удобен для компонентной модели разработки; + Изменения кода приложения не требуют перекомпиляции конфигурации. Применим скорее на другом уровне: для управления компонентами в сложных многомодульных приложений
  24. Макрос WALLAROO_REGISTER для генерации фабричных методов создания обьектов и их генерации в реестре wallaroo; Явное создание и связывание обьектов: изменяется глобальный реестр wallaroo;
  25. Возможность изменять граф зависимостей во время выполнения приложения; Ограничение на количество аргументов в конструкторе.
  26. Дублирование сигнатуры конструктора или макрос INJECT для определения сигнатуры конструктора; Разбор сигнатуры для формирования списка зависимостей; Объекты создаются с помощью графа зависимостей классов и списка соответствия интерфейсов и реализаций
  27. Для разбора сигнатуры конструкторов используется [C++ 11] type traits; В результате разбора формируется граф зависимостей классов; Обьекты создаются на основе списка соответствия интерфейсов и реализаций из класса injector и графа зависимостей классов;
  28. Собрав воедино результаты оценок фрейморков согласно нашим требованиям, получили следующую таблицу. Два лидера: Fruit и BoostDI. Оба проекта активно ращвиваются, но еще сыроваты. В частности Fruit недостаточно настраиваем (не поддерживает кастомные аллокаторы, умные указатели и др.), а Boost.DI один инжектор на все компоненты, что возвращает фреймворк к минусам SL.
  29. (Сергей) Подведем итоги (Сергей) Мы рассмотрели опыт использования DI & SL на реальном проекте. Сделали вывод про предпочтительность DI (хотя и он не идеален); (Сергей) Рассмотрели DI-фреймворки. (Сергей) В отличие от Java/C# на текущий момент на C++ нет признанныз фреймворков такого типа. Периодически появляются и исчезают; (Сергей) C++11/14 открывает перспективы развития метапрограммирования, можно ожидать дальнейшего развития Compile-Time DIFw (Сергей) Для своего проекта сделали вывод о manual DI пока (но надеемся на лучшее). (Сергей) Надо понимать, что для других проектов и других целей критерии могут быть отличные. Например ABI. В частности, когда речь идет не о связывании отдельных объектов а крупноблочных компонентов мы планируем продолжать использовать Service Locator. (Сергей) Спасибо, вопросы