Внедрение зависимости (Dependency Injection — DI) означает передачу (внедрение) одной или более зависимости какому-либо объекту (клиенту, компоненту) таким образом, что после внедрения эта зависимость становится частью состояния объекта. Это немного напоминает паттерн проектирования Стратегия, с той лишь разницей, что стратегия задаётся лишь однажды — в конструкторе. DI позволяет создавать более слабо-связанную архитектуру приложения, которая лучше поддаётся поддержке и тестированию.
Итак, ещё раз плюсы:
Boost.DI это библиотека для реализации внедрения зависимости в С++. Для её использования нужно лишь включить в свой код один заголовочный файл. Цель библиотеки — упростить создание объектов с помощью автоматического внедрения зависимостей:
А вообще-то всё, что вам необходимо для работы с библиотекой, этой файл di.hpp
Давайте предположим, что все примеры ниже включают boost/di.hpp и определяют пространство имён di как алиас boost::di.
Примеры
Ещё примеры
Примеры
Ещё примеры
Примеры
Примеры
Ещё примеры
Примеры
Примеры
Примеры
Ещё примеры
Окружение
Пример
Окружение
Легенда
Лицензия: Boost Software License, Version 1.0
Нюанс: библиотека пока не входит в Boost, а лишь находится в "инкубаторе".
Источник: habrahabr.ru
Итак, ещё раз плюсы:
- Уменьшает связность компонент (отделяет бизнес-логику от создания объекта)
- Позволяет писать более поддерживаемый код (в одни и те же объекты мы легко можем внедрять разные зависимости)
- Позволяет писать более тестируемый код (мы можем легче использовать стабы и моки)
Без внедрения зависимости | С внедрением зависимости |
---|---|
Boost.DI это библиотека для реализации внедрения зависимости в С++. Для её использования нужно лишь включить в свой код один заголовочный файл. Цель библиотеки — упростить создание объектов с помощью автоматического внедрения зависимостей:
- Уменьшение количества «узких мест» в коде — никаких лишних фабрик, никакого создания объектов лишь в определённом порядке
- Упрощение поддержки кода — изменение сигнатуры конструктора не повлияет на конфигурацию DI
- Упрощение тестирование — автоматическая инъекция моков
- Более хороший контроль над тем, что и когда создаётся
- Лучшее понимание кода в плане иерархии объектов
Ручное внедрение зависимости | Boost.DI |
---|---|
Ещё раз — зачем использовать внедрение зависимости
С чего начать?
- Возьмите компилятор с поддержкой С++14 (Clang-3.4+, GCC-5.0+). Библиотека Boost не требуется
- Прочитайте этот документ
- Прочитайте учебник
- Прочитайте документацию
А вообще-то всё, что вам необходимо для работы с библиотекой, этой файл di.hpp
Давайте предположим, что все примеры ниже включают boost/di.hpp и определяют пространство имён di как алиас boost::di.
Инжектор
Создание пустого инжектора | Тест |
---|---|
Привязки
Примеры
Ещё примеры
Привязка интерфейса к реализации | Тест |
---|---|
Привязка нескольких интерфейсов к одной реализации | Тест |
---|---|
Привязка типа к значению, вычисляемому на этапе компиляции | Тест |
---|---|
Привязка типа к значению | Тест |
---|---|
Внедрение
Примеры
Ещё примеры
Внедрение через обычный конструктор | Тест |
---|---|
Внедрение через аггрегацию | Тест |
---|---|
Внедрение через конструктор при наличии нескольких конструкторов (будет выбран тот, у которого наибольшее число параметров) | Тест |
---|---|
Внедрение через конструктор при наличии вариантов выбора (использование BOOST_DI_INJECT) | Тест |
---|---|
Внедрение через конструктор при наличии вариантов выбора (использование BOOST_DI_INJECT_TRAITS) | Тест |
---|---|
Внедрение через конструктор при наличии вариантов выбора (использование di::ctor_traits) | Тест |
---|---|
Аннотации
Примеры
Внедрение через аннотированные конструкторы | Тест |
---|---|
Внедрение через аннотированные конструкторы с использованием именованных параметров | Тест |
---|---|
Внедрение через аннотированные конструкторы с вынесением реализации конструктора | Тест |
---|---|
Внедрение через аннотированные конструкторы с использованием di::ctor_traits | Тест |
---|---|
Области видимости
Примеры
Ещё примеры
Вывод области видимости (по-умолчанию) | Тест |
---|---|
Тип | Выведенная область видимости |
---|---|
T | unique |
T& | ошибка — должен быть связан как external |
const T& | unique (временный) |
T* | unique (передача владения) |
const T* | unique (передача владения) |
T&& | unique |
unique_ptr | unique |
shared_ptr | singleton |
weak_ptr | singleton |
Уникальная область видимости | Тест |
---|---|
Разделяемая область видимости (в пределах потока) | Тест |
---|---|
Синглтон (разделяем между потоками) | Тест |
---|---|
Область видимости сессии | Тест |
---|---|
Внешняя область видимости | Тест |
---|---|
Специальная область видимости | Тест |
---|---|
Модули
Примеры
Модуль | Тест |
---|---|
Модуль, открывающий тип | Тест |
---|---|
Модуль, открывающий несколько типов | Тест |
---|---|
Модуль открытого типа с аннотацией | Тест |
---|---|
Провайдеры
Примеры
«no throw»-провайдер | Тест |
---|---|
Политики
Примеры
Ещё примеры
Определение политик конфигурации (дамп типов) | Тест |
---|---|
Определение политик конфигурации (развёрнутый дамп типов) | Тест |
---|---|
Политика «может быть сконструирован» | Тест |
---|---|
Производительность на рантайме
Окружение
- x86_64 Intel® Core(TM) i7-4770 CPU @ 3.40GHz GenuineIntel GNU/Linux
- clang++3.4 -O2 / gdb -batch -ex 'file ./a.out' -ex 'disassemble main'
Создание типа без привязок | Asm x86-64 (то же, что «return 0») |
---|---|
Создание типа с привязкой объекта | Asm x86-64 (то же, что «return 42») |
---|---|
Создание именованного типа | Asm x86-64 (то же, что «return 42») |
---|---|
Создание привязки интерфейса к реализации | Asm x86-64 (то же, что «make_unique») |
---|---|
Создание привязки интерфейса через модуль | Asm x86-64 (то же, что «make_unique») |
---|---|
Создание привязки интерфейса через открытый модуль | Asm x86-64 цена = вызов виртуального метода |
---|---|
Производительность на этапе компиляции
Пример
Окружение
- x86_64 Intel® Core(TM) i7-4770 CPU @ 3.40GHz GenuineIntel GNU/Linux
- clang++3.4 -O2
Заголовочный файл Boost.DI | Время [сек] |
---|---|
0.165 |
Легенда
- ctor = «голый» конструктор: c(int i, double d);
- inject = внедрение в конструктор: BOOST_DI_INJECT(c, int i, double d);
- all = все типы в модуле доступны: auto configure();
- exposed = один тип в модуле доступен: di::injector<c> configure();
- 4248897537 объектов создано
- 132 разных типа
- 10 модулей
- 1862039751439806464 объекта создано
- 200 разных типов
- 10 модулей
- 5874638529236910091 объект создан
- 310 разных типов
- 100 разных интерфейсов
- 10 модулей
Диагностические сообщения
Создание интерфейса без привязки к реализации | Сообщение об ошибке |
---|---|
Неоднозначность привязки | Сообщение об ошибке |
---|---|
Создание объекта без привязок при политике, требующей их | Сообщение об ошибке |
---|---|
Неверный синтаксис аннотаций (NAMED вместо named) | Сообщение об ошибке |
---|---|
Конфигурация
Макрос | Описание |
---|---|
Похожие библиотеки
Лицензия: Boost Software License, Version 1.0
Нюанс: библиотека пока не входит в Boost, а лишь находится в "инкубаторе".
Источник: habrahabr.ru
Комментариев нет:
Отправить комментарий