Здравствуйте, Хон Гиль Дон, Вы писали:
ХГД>Здравствуйте, Abyx, Вы писали:
Ш>>>Это глупость. Например, хип есть глобальный объект и ты им (как правило неявно) пользуешься в большинстве программ.
A>>во многих библиотеках делают возможность задать свои функции аллокации/деаллокации, и хип напрямую не используется.
ХГД>Ага, одна пара маллок/фри на всю либу. То есть глобальные. Последовательного применения dependency injection, шоп например в каждый объект тащить аллокатор, логгер и конфиг, я в реальном вменяемом коде ни разу пока не видел. Не, я допускаю, что области где они сплошь требуются, бывают, но советовать это по умолчанию по-моему перебор.
ну вот есть 7zip, там так и сделано.
если бы оттуда COM выпилить — был бы совсем хороший код %)
а вообще если использовать что-то типа DI-контейнера/сервис-локатора, то код получается довольно простым.
using MyDIContainer = std::tuple<Logger*, Config*, ...>;
class Foo {
public:
Foo(const MyDIContainer& di_container) {
auto cfg = get<Config*>(di_container); // std::get
...
log(di_container, "something", 123); // calls "if (auto logger = get<Logger*>(di_container)) logger->log(args...);"
...
auto bar = allocate<Bar>(di_container, 456); // calls "get<Allocator*>(di_container)->Create<T>(args...);"
};
};
если сделать вспомогательный базовый класс, часть бойлерплейта можно убрать.
Ш>>>То же самое относится к целому ряду объектов, например стандартные потоки ввода-вывода в консольных приложениях.
A>>тожесамое. если где-то так написано, ты не можешь по-нормальному реюзнуть такой код в GUI программе.
ХГД>Чтобы с этим не было проблем, достаточно обеспечить подключаемые реализации глобальных объектов с разумными умолчаниями. Например, логгер никуда не выводит, аллокатор вызывает CRT'шные malloc/free, конфиг возвращает какие-то дефолты. А DI уместнее оставить для случаев, где неявных границ нет, а разное поведение требуется.
Всё это хорошо до тех пор, пока тебе не понадобится например запустить две функции параллельно, и дать каждой свой логгер.
Или вызвать void foo(function<void()> delegate); так чтобы код в foo писал в логгер, а delegate туда не писал.
Можно конечно запилить демультиплексор, но все же лучше иметь возможность задавать свои логи.