.. не Dependency Injection, а именно Inversion of Control я смотрю в плюсах не популярен. В мире Java без этого тебя сначала засмеют, а потом когда поймут что ты не унимаешься - то изобьют.
Что я подразумеваю под IoC
- Есть контейнер, в которым по определенным ключам (типы, строки) регистрируются классы
- Контейнер обязан уметь создавать инстансы каждого из классов, если надо подставляя ему или в конструктор или как-то по другому его зависимости
- Группы регистраций классов можно обьединять в модули, которые просто устанавливаются подключением к основном контейнеру. Они тогда предоставлют или требуют другие класса для своей работы. По сути как паззл.
- В тестах можно заменять целы модули указывая «запусти мне весь контейнер, но пожалуйста замени MyClass на MyMockClass»
Пример на псевдокоде который вроде бы как С++
class IB {
public:
int value() = 0;
};
class B : public IB {
public:
int value() {
return 1;
}
};
class A {
A(std::shared_ptr<IB> b) : b_(b) {}
int value() {
return b_->value();
}
private:
std::shared_ptr<IB> b_;
};
void MyModule(Container& c) {
c.RegisterAs<IB, B>(CREATE(
B()
));
c.Register<A>(CREATE(
A(INJECT(IB))
));
}
int main() {
Container c;
MyModule(c);
std::cout << c.Get<A>()->value() << std::endl;
return 0;
}
Вместо shared_ptr может вполне быть unique_ptr и B будет не синглтоном внутри контейнера, а будет создаваться отдельно для каждого класса-пользователя. Слово синглтон перестает быть пугающим, потому что это не глобальный синглтон, а синглтон в одном контейнере, плюс легко тестируется и нету проблем с неправильной инициализацией.
В тесте запросто выполняется MyModule, а потом регистрация IB меняется на MockB.
Примеры существующих фреймворков
https://github.com/google/fruit
https://github.com/ybainier/Hypodermic
Вопрос, чего не популярно? Врядли аргументы оправданы о том что это лишнее и все такое актуальны, пакетные менеджеры это решают. Зато тестирование на уровень легче, что уже с десяток лет используется в Java во все поля