Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Хорошее или нет использование extern?


Автор: jonie 10.6.2009, 22:26
Недавно производил небольшой рефакторинг одного солюшена. В нем в каждом проекте были скопипащены одни и теже файлы логгера, которые отличались только именем файла логгера, зашитого "рядом" через define (да, я бы тоже того кто делал убил бы, чтобы Земля не мучалась)...

Итогово у меня получилось примерно такое:
я сделал common.lib с классом логгера, который подключил к каждому проекту.
В common.lib мною был определен extern tstring LOG_NAME  (бывший дефайн).
/* я не сделал передачу имени в конструктор, т.к. логгер оформлен как синглетон, и где его первое использование будет в проекте сказать нельзя */

в кажом проекте, куда включен common.lib мною был прошит tstring LOG_NAME, чтобы логгер нашел его.

Считается ли это ужасом?

Выносить логгер в динамическую либу запрещено.

Автор: azesmcar 11.6.2009, 00:58
jonie

Ничего плохого не вижу, extern и существует для подобных ситуаций. Вообще, для того чтобы говорить о том что какая либо конструкция - зло, надо иметь достаточно оснований. Тут я вообще оснований не вижу. Возможно если подумать, теоретически можно придумать решение и покрасивее, но зла я в этом решении однозначно не вижу. smile 

Цитата(jonie @  10.6.2009,  22:26 Найти цитируемый пост)
Считается ли это ужасом?

 smile 

мое лично мнение

Автор: Earnest 11.6.2009, 08:10
Когда имеешь дело со старым плохим кодом, который нужно использовать как есть, ничто ужасом не считается.
Насчет практических соображений. В данном случае лучше глобальную переменную заменить парой: статическая переменная, видимая только в контексте библиотеки-логгера (пишу статическая, хотя она может продолжать оставаться глобальной, но не выходить за пределы библиотеки) + функция для ее установки, типа SetLogContext. Чем это лучше:
во-первых, все безобразие скрывается (чем локализованнее ужас, тем он менее ужасен), во-вторых, при поддержке и изменениях проще справиться с функцией (найти все вхождения). Для этого ее имя можно сделать подлиннее...

Автор: xvr 11.6.2009, 11:46
Цитата(Earnest @ 11.6.2009,  08:10)
В данном случае лучше глобальную переменную заменить парой: статическая переменная, видимая только в контексте библиотеки-логгера (пишу статическая, хотя она может продолжать оставаться глобальной, но не выходить за пределы библиотеки) + функция для ее установки, типа SetLogContext. 

Не сработает - Logger оформлен как Singleton, поэтому невозможно предсказать что произойдет раньше - создасться собственно Logger (который подхватит имя лог файла), или вызовут функцию SetLogContext (которое это имя должна установить).

jonie

У меня был аналогичный модуль (логер), и у него была аналогичная переменная (имя компоненты) и она задавалась так же, как у тебя.

Видимо в этом есть какая то сермяжная правда  smile 

PS. Только я ее задание завернул в дефайн, что бы не светить наружу детали реализации.
Вот так
Код

HR_MODULE("mainserver");


В принципе имя файла для лога можно выводить автоматом из имени исполняемого модуля (или из имени exe+имя dll - для dll)

Автор: Earnest 11.6.2009, 12:29
Цитата(xvr @  11.6.2009,  12:46 Найти цитируемый пост)
Не сработает - Logger оформлен как Singleton, поэтому невозможно предсказать что произойдет раньше 

Ерунда, если нужно гарантировать установку имени раньше первого вызова логгера, то это несложно сделать, особенно если имя устанавливается один раз. 

Автор: xvr 11.6.2009, 13:27
Цитата(Earnest @ 11.6.2009,  12:29)
Цитата(xvr @  11.6.2009,  12:46 Найти цитируемый пост)
Не сработает - Logger оформлен как Singleton, поэтому невозможно предсказать что произойдет раньше 

Ерунда, если нужно гарантировать установку имени раньше первого вызова логгера, то это несложно сделать,

И как? Особенно если учесть, что логгер может быть вызван из конструкторов глобальных статических объектов. И заранее неизвестно где и сколько таких объектов будет.

Автор: xvr 11.6.2009, 13:51
Забыл добавить.
Все же одно отличие в моей реализации было - я использовал для задания имени модуля не string а char [] 
Код

#define HR_MODULE(nm) char hr_module_name[]=nm
В этом случае логгер мог быть спокойно вызван из любого места, т.к. char [] (в отличие от string) не требует вызовов конструктора для своей инициализации, и к моменту первого обращения к логеру всегда будет в правильном (инициализированном) состоянии

Автор: Earnest 11.6.2009, 15:32
Делов-то. Например, обернуть функцию вызова логгера другой, в которую включить вызов устновки имени. Это если действительно логгер может инициализировать не в коде.

Автор: ДокторТуамОсес 11.6.2009, 15:43
Цитата(jonie @  10.6.2009,  22:26 Найти цитируемый пост)
Недавно производил небольшой рефакторинг одного солюшена. В нем в каждом проекте были скопипащены одни и теже файлы логгера, которые отличались только именем файла логгера, зашитого "рядом" через define (да, я бы тоже того кто делал убил бы, чтобы Земля не мучалась)...

Ничего не понял. А так хотелось бы тоже понять о чём речь. Чувствую, что речь идёт о чём-то интересном. 

Не могли бы Вы сказать тоже самое но технически граммотным языком?

Автор: jonie 11.6.2009, 16:05
Цитата(Earnest @ 11.6.2009,  15:32)
Делов-то. Например, обернуть функцию вызова логгера другой, в которую включить вызов устновки имени. Это если действительно логгер может инициализировать не в коде.

адаптер? дело-то конечно, хорошее и правильное, но там есть функции с переменным аргументов, и с ними будут проблемы при вызове исходного логгера.

xvr в моей реализации также невозможно чтобы логгер был инициализирован, а tstring нет. Любой вызов логгера, который использует tstring вызовет её конструктор, разве нет?

Автор: xvr 11.6.2009, 17:32
Цитата(jonie @ 11.6.2009,  16:05)
xvr в моей реализации также невозможно чтобы логгер был инициализирован, а tstring нет. Любой вызов логгера, который использует tstring вызовет её конструктор, разве нет?

Нет. Если tstring физически не помещен в класс логера (а он туда не может быть помещен, т.к. описывается отдельно в каком то файле), то он будет статическим объектом и его конструктор будет вызван вместе со всеми конструкторами других статических объектов.
Если другой статический объект создасться раньше, и из своего конструктора позовет логер, то логер будет читать непроинициализированную tstring

Добавлено через 3 минуты и 8 секунд
Цитата(Earnest @ 11.6.2009,  15:32)
Делов-то. Например, обернуть функцию вызова логгера другой, в которую включить вызов устновки имени. Это если действительно логгер может инициализировать не в коде.

Эту функцию придется где то расположить и написать. Чем (с точки зрения применения) это будет отличаться от макроса HR_MODULE, который будет так же расположен в том же самом месте?

Автор: Fazil6 12.6.2009, 10:11
Цитата(xvr @  11.6.2009,  17:32 Найти цитируемый пост)
из своего конструктора позовет логер, то логер будет читать непроинициализированную tstring

сказали же, обеспечить инициализацию tstring - как два пальца об асфальт. Заменяешь эту переменную функцией и все.

Добавлено @ 10:15
Цитата(xvr @  11.6.2009,  17:32 Найти цитируемый пост)
Чем (с точки зрения применения) это будет отличаться от макроса HR_MODULE, который будет так же расположен в том же самом месте?

ну хотябы областью видимости... 

Автор: xvr 12.6.2009, 12:04
Цитата(Fazil6 @ 12.6.2009,  10:11)
Цитата(xvr @  11.6.2009,  17:32 Найти цитируемый пост)
из своего конструктора позовет логер, то логер будет читать непроинициализированную tstring

сказали же, обеспечить инициализацию tstring - как два пальца об асфальт. Заменяешь эту переменную функцией и все.

Ну это не совсем 'инициализация tstring', но вполне нормальный вариант.
Цитата

Добавлено @ 10:15
Цитата(xvr @  11.6.2009,  17:32 Найти цитируемый пост)
Чем (с точки зрения применения) это будет отличаться от макроса HR_MODULE, который будет так же расположен в том же самом месте?

ну хотябы областью видимости...
Да, это минус  smile Но функция переносит больше деталей реализации из логера в программу, а это плюс макросу. Кроме того, содержимое макроса - это определение глобальной переменной, что в принципе (по областям видимости, использованию определений и пр) аналогично определению функции. Если мы уберем макрос и заставим писать его содержимое вместо его использования, получится практически 1 в 1 вариант с функцией.
Так что нельзя считать, что функция лучше  smile 

Кстати, имя файла для логера (точнее имя модуля, имя файла должно выводится из него) вообще можно задать макросом с командной строки компилятору (через -D). Такое решение совершенно прозрачно для программы в целом, но добавляет лишний шаг в настройку компиляции (что тоже не фонтан   smile )

Автор: andrew_121 12.6.2009, 12:35
Цитата(ДокторТуамОсес @  11.6.2009,  15:43 Найти цитируемый пост)
Не могли бы Вы сказать тоже самое но технически граммотным языком? 

Думаю могли бы. Но здесь не зазубры и ботаники.
К Вашему сведению, слово граммотным, пишется с одним м smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)