Re[4]: Как наиболее корректно работать с глобальными данными
От: Abyx Россия  
Дата: 03.07.15 20:57
Оценка:
Здравствуйте, Хон Гиль Дон, Вы писали:

ХГД>Здравствуйте, 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 туда не писал.
Можно конечно запилить демультиплексор, но все же лучше иметь возможность задавать свои логи.
In Zen We Trust
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.