Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > 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 и существует для подобных ситуаций. Вообще, для того чтобы говорить о том что какая либо конструкция - зло, надо иметь достаточно оснований. Тут я вообще оснований не вижу. Возможно если подумать, теоретически можно придумать решение и покрасивее, но зла я в этом решении однозначно не вижу. ![]() ![]() мое лично мнение |
Автор: Earnest 11.6.2009, 08:10 |
Когда имеешь дело со старым плохим кодом, который нужно использовать как есть, ничто ужасом не считается. Насчет практических соображений. В данном случае лучше глобальную переменную заменить парой: статическая переменная, видимая только в контексте библиотеки-логгера (пишу статическая, хотя она может продолжать оставаться глобальной, но не выходить за пределы библиотеки) + функция для ее установки, типа SetLogContext. Чем это лучше: во-первых, все безобразие скрывается (чем локализованнее ужас, тем он менее ужасен), во-вторых, при поддержке и изменениях проще справиться с функцией (найти все вхождения). Для этого ее имя можно сделать подлиннее... |
Автор: xvr 11.6.2009, 11:46 | ||||
Не сработает - Logger оформлен как Singleton, поэтому невозможно предсказать что произойдет раньше - создасться собственно Logger (который подхватит имя лог файла), или вызовут функцию SetLogContext (которое это имя должна установить). 2 jonie У меня был аналогичный модуль (логер), и у него была аналогичная переменная (имя компоненты) и она задавалась так же, как у тебя. Видимо в этом есть какая то сермяжная правда ![]() PS. Только я ее задание завернул в дефайн, что бы не светить наружу детали реализации. Вот так
В принципе имя файла для лога можно выводить автоматом из имени исполняемого модуля (или из имени exe+имя dll - для dll) |
Автор: xvr 11.6.2009, 13:27 | ||||
И как? Особенно если учесть, что логгер может быть вызван из конструкторов глобальных статических объектов. И заранее неизвестно где и сколько таких объектов будет. |
Автор: xvr 11.6.2009, 13:51 | ||
Забыл добавить. Все же одно отличие в моей реализации было - я использовал для задания имени модуля не string а char []
|
Автор: Earnest 11.6.2009, 15:32 |
Делов-то. Например, обернуть функцию вызова логгера другой, в которую включить вызов устновки имени. Это если действительно логгер может инициализировать не в коде. |
Автор: ДокторТуамОсес 11.6.2009, 15:43 | ||
Ничего не понял. А так хотелось бы тоже понять о чём речь. Чувствую, что речь идёт о чём-то интересном. Не могли бы Вы сказать тоже самое но технически граммотным языком? |
Автор: jonie 11.6.2009, 16:05 | ||
адаптер? дело-то конечно, хорошее и правильное, но там есть функции с переменным аргументов, и с ними будут проблемы при вызове исходного логгера. xvr в моей реализации также невозможно чтобы логгер был инициализирован, а tstring нет. Любой вызов логгера, который использует tstring вызовет её конструктор, разве нет? |
Автор: xvr 11.6.2009, 17:32 | ||||
Нет. Если tstring физически не помещен в класс логера (а он туда не может быть помещен, т.к. описывается отдельно в каком то файле), то он будет статическим объектом и его конструктор будет вызван вместе со всеми конструкторами других статических объектов. Если другой статический объект создасться раньше, и из своего конструктора позовет логер, то логер будет читать непроинициализированную tstring Добавлено через 3 минуты и 8 секунд
Эту функцию придется где то расположить и написать. Чем (с точки зрения применения) это будет отличаться от макроса HR_MODULE, который будет так же расположен в том же самом месте? |
Автор: Fazil6 12.6.2009, 10:11 | ||||
сказали же, обеспечить инициализацию tstring - как два пальца об асфальт. Заменяешь эту переменную функцией и все. Добавлено @ 10:15
ну хотябы областью видимости... |
Автор: xvr 12.6.2009, 12:04 | ||||||||
Ну это не совсем 'инициализация tstring', но вполне нормальный вариант.
![]() Так что нельзя считать, что функция лучше ![]() Кстати, имя файла для логера (точнее имя модуля, имя файла должно выводится из него) вообще можно задать макросом с командной строки компилятору (через -D). Такое решение совершенно прозрачно для программы в целом, но добавляет лишний шаг в настройку компиляции (что тоже не фонтан ![]() |
Автор: andrew_121 12.6.2009, 12:35 | ||
Думаю могли бы. Но здесь не зазубры и ботаники. К Вашему сведению, слово граммотным, пишется с одним м ![]() |