реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Объявления, Как принято делать, и кто как реально делает.
SasaVitebsk
сообщение Oct 14 2009, 18:34
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Раньше у меня не было таких проблем. Обычно создавал группу файлов. Как правило все файлы были достаточно обособленными и я их объединял на этапе линковки. Если были групповые общие объявления, то я их делал в main, а в других объявлял как extern.

Проблема возникла в одном проекте. Он получил развитие и теперь существует в нескольких реинкарнациях с различными модификациями и процами. Тем не менее там есть очень крупные общие блоки. Столкнувшись, с проблемой поддержки - пришёл к необходимости общую часть исходников выделить в отдельные файлы/процедуры. А иначе, при внесении изменений приходилось править все проекты. Выделил и переписал, с учётом унификации.

А теперь вопрос.
Эти блоки используют общие глобальные переменные. Как их правильно объявить, чтобы было удобнее использовать и поддерживать, а также было меньше разной писанины?
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 14 2009, 19:13
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Может стоит объединить переменные в глобальную структуру?
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Oct 14 2009, 19:25
Сообщение #3


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Не знаю правда ли, но я недавно прочел такую вещь:
Цитата
56. Не захламляйте область глобальных имен
Беспорядок в области глобальных имен является характерной проблемой
для среды групповой разработки. Вам не очень понравится спрашивать
разрешение от каждого участника группы каждый раз, когда вы вводите
новый идентификатор. Поэтому:
• Локальная переменная всегда более предпочтительна, чем член класса.
• Член класса всегда более предпочтителен, чем статическая глобальная
переменная.
• Статическая глобальная переменная всегда более предпочтительна,
чем настоящая глобальная переменная.
Статический глобальный идентификатор не экспортируется из файла .c,
поэтому он невидим из других модулей. Применяйте модификатор
static к как можно большему числу глобальных идентификаторов
(переменным и функциям). Ключ доступа private в определении класса
еще лучше. Идентификатор, определенный локально внутри
подпрограммы, лучше всех, потому что он изолирован от всех других
функций в программе.
Вывод: избегайте препроцессора. Так как у макроса такая большая
область видимости, то он, по сути, то же самое, что и глобальная
переменная.
Ален И. Голуб Правила программирования на Си и Си++
А ещё где-то он писал, что за более чем 20летнюю практику программирования он может сказать, что реально обычно требуется пять-десять действительно глобальных переменных на большой проект.
Поэтому Вам следует пересмотреть тактику проектирования модулей и, возможно всё станет куда более прозрачно.

P.S. книгу тоже к прочтению рекомендую, хотя тут прозвучала мысль, что она уже очень старая и некоторые вещи сейчас могут утратить актуальность...это тоже похоже на правду.
В общем её(как и всё в этой жизни) нужно использовать с умом smile.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 14 2009, 19:38
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(rezident @ Oct 14 2009, 22:13) *
Может стоит объединить переменные в глобальную структуру?

Проект достаточно крупный. Переменных много. В том числе и структуры тоже есть.

Цитата(sigmaN @ Oct 14 2009, 22:25) *
А ещё где-то он писал, что за более чем 20летнюю практику программирования он может сказать, что реально обычно требуется пять-десять действительно глобальных переменных на большой проект.

В общем так обычно у меня и было. Поэтому вопрос и не возникал. А тут специфика.
Представте что модуль выполняет обработку. А-В-С. Причём часть тела модуля B является специфической для разных проектов.
Если не резать, то всё нормально, но тогда придётся поддерживать 4 разных проекта. Но часть B является незначительной по сравнению с объёмом самого проекта. Остальные части удалось формализовать. Частично пришлось переписать с прицелом на "универсальность". В результате со всеми проектами можно работать по единым правилам. А то раньше - где-то подправишь - в другом вылазит.

За книгу спасибо, попробую почитать.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Oct 14 2009, 19:43
Сообщение #5


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Ну тут, ИМХО, кроме Вас никто не решит проблему.
Я иногда по два-три раза переписываю модули. И причиной является именно неудачное сцепление с остальными smile.gif
Хотя на меня ровняться не стоит особо - я ещё относительно неопытный программист.


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Faradey
сообщение Oct 14 2009, 20:03
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 127
Регистрация: 31-05-06
Из: Belarus, Minsk
Пользователь №: 17 638



как вариант, объедините специфические "переменные" в группы и передавайте в исп. ф-ции указатель на них:
Код
extern MyType my_type;
extern int f1( void *p );

...

int res = f1( ( void *)&my_type );


--------------------
Завтра пойму, что нужно было сделать вчера...
Go to the top of the page
 
+Quote Post
kurtis
сообщение Oct 14 2009, 21:32
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Цитата(SasaVitebsk @ Oct 14 2009, 22:38) *
В общем так обычно у меня и было. Поэтому вопрос и не возникал. А тут специфика.
Представте что модуль выполняет обработку. А-В-С. Причём часть тела модуля B является специфической для разных проектов.
Если не резать, то всё нормально, но тогда придётся поддерживать 4 разных проекта. Но часть B является незначительной по сравнению с объёмом самого проекта. Остальные части удалось формализовать. Частично пришлось переписать с прицелом на "универсальность". В результате со всеми проектами можно работать по единым правилам. А то раньше - где-то подправишь - в другом вылазит.


Попробуй-те использовать С++ !
Пишете какой-то виртуальный базовый класс-родитель, который имеет только интерфейс, никакого кода, а потом наследуете каждый конкретный модуль от базового класса и пишете свой, специфический для данного модуля код (т.е. будет класс_А, класс_Б и тд). Константы и перечисления можно запрятать в класс и никто снаружи их не будет видеть. Ну а дальше уже пишите технологию, которая через интерфейс базового класса работает с Вашими модулями. Ну и для пущей уверенности, запихать все по своим пространствам имен (namespace).
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 14 2009, 22:24
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(kurtis @ Oct 15 2009, 00:32) *
Попробуй-те использовать С++ !

Похоже что было бы оптимально. Там и так уже практически готовая работа с объектами. Но всё равно надо переписывать, а это сейчас влом. Отладка займёт слишком много времени. Проект вылизывался года полтора, чтобы ни сучка ни задоринки.

Я просто думал, что существуют какие-то "стандартные решения" на этот случай.

Всем ответившим - спасибо.
smile.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 14 2009, 22:41
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(kurtis @ Oct 15 2009, 00:32) *
Константы и перечисления можно запрятать в класс и никто снаружи их не будет видеть....

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Oct 15 2009, 03:09
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Ранее тоже столкнулся с тем, что большая часть кода активно используется в нескольких проектах. Соответственно выделил ее в некоторый фреймворк. Фреймворк тоже состоит из двух частей - платформонезависимой и платформозависимой.

Все логически законченные модули обозвал как сервисы, для общения между сервисами написал систему передачи сообщений (с интересной мне особенностью - сервис передающий сообщение ничего не знает о том сервисе (сервисах), которые его получат. В частном случае их (получаетелей) вообще может не быть. Чем-то напоминает идеологию шины CANbus (каждое сообщение характеризуется не адресом получателя, а своим собственным идентификатором).

Все это написано на С++
Если будет интерес - могу выложить код
Go to the top of the page
 
+Quote Post
dxp
сообщение Oct 15 2009, 04:18
Сообщение #11


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(kurtis @ Oct 15 2009, 04:32) *
Попробуй-те использовать С++ !
Пишете какой-то виртуальный базовый класс-родитель,

Вы хотели сказать "абстрактный базовый класс"?

Цитата(SasaVitebsk @ Oct 15 2009, 05:24) *
Похоже что было бы оптимально. Там и так уже практически готовая работа с объектами.

Тоже за С++. Только не уверен, что тут нужна иерархия полиморфных классов (т.е. с виртуальными функциями). Мне кажется, что тут достаточно будет просто определить интерфейсы (как там что с чем взаимодействует), и из этого уже автоматом получаются интерфейсы классов - фукнции-члены в public части класса. Все, далее представление и реализации классов можно будет спокойно менять - пока интерфейсы неизменны, совместимость будет на месте. Таким образом можно отделить интерфейсы от реализации. В объектом программирование оно называется инкапсуляцией.

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

Цитата(zltigo @ Oct 15 2009, 05:41) *
Для собственно данных существенных преимуществ перед банальным запихиванием всего вышеперечисленного в банальную сишную структуру нет.

Данные - они не сами по себе, с ними код работает. И данные лучше спрятать подальше от произвольного доступа, а наружу выдать только допустимые методы работы с данными. Поэтому данные надо не в структуру спрятать, а в класс, в private секцию. Разница с сишной структурой будет более, чем значительна.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Flexz
сообщение Oct 15 2009, 07:07
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



Вобщем-то, все что вы предлагаете можно и на С реализовать, не применяя классы.
Абстрактный базовый класс? прототипы функций в .h-файле
private-секция? static структура.
Нужно несколько экземпляров одинакового модуля в рамках одного проекта? Передавайте указатель на эту структурку, преобразовав его к void*, дабы вызывающий код не лазил куда не следует (идиома pimpl).
Несколько реализаций одного базового (абстрактного) класса, в данном конктретном случае, как я понял, не нужны, но и их при желании можно реализовать с помощью структуры с набором указателей на функции.

ИМХО в данном случае это лучше, т.к. перетащить большой готовый проект с С на С++ в одно действие не выйдет.
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Oct 15 2009, 07:19
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(Flexz @ Oct 15 2009, 10:07) *
ИМХО в данном случае это лучше, т.к. перетащить большой готовый проект с С на С++ в одно действие не выйдет.


Никто не спорит, что можно заниматься объектным программированием на Си, Другое дело - насоклько это удобно (ИМХО - как ездить на велосипеде без педалей. Можно, но пешком быстрее)) ).

Насчет приведения к (void*) - это путь для всевозможных трудноуловимых ошибок, тк рано или поздно будет передан не тот объект, который ожидаем smile.gif
Одно из достоинств С++ - строгий контроль за типом данных. Да простейший пример - очереди. Попробуйте реализовать универсальную очередь на Си и на С++, и почувствуйте разницу smile.gif
Причина редактирования: Излишнее цитирование.
Go to the top of the page
 
+Quote Post
dxp
сообщение Oct 15 2009, 07:30
Сообщение #14


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Flexz @ Oct 15 2009, 14:07) *
Вобщем-то, все что вы предлагаете можно и на С реализовать, не применяя классы.
Абстрактный базовый класс? прототипы функций в .h-файле
private-секция? static структура.
Нужно несколько экземпляров одинакового модуля в рамках одного проекта? Передавайте указатель на эту структурку, преобразовав его к void*, дабы вызывающий код не лазил куда не следует (идиома pimpl).

Не берусь судить в целом, но советовать использовать void* ни в коем случае не стал бы. Работа через void* - это хак, и в если его где и оправдано применять, так не от хорошей жизни. Случаи использования void* надо сводить к минимуму, в идеале - к нулю.

Цитата(Flexz @ Oct 15 2009, 14:07) *
Несколько реализаций одного базового (абстрактного) класса, в данном конктретном случае, как я понял, не нужны, но и их при желании можно реализовать с помощью структуры с набором указателей на функции.

ИМХО в данном случае это лучше, т.к. перетащить большой готовый проект с С на С++ в одно действие не выйдет.

Может и лучше. Но если уж оставаться на С, то и концепции С++ лучше не тащить, от них при ручной реализации будет больше проблем, чем пользы.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Flexz
сообщение Oct 15 2009, 08:12
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



Цитата
Насчет приведения к (void*) - это путь для всевозможных трудноуловимых ошибок, тк рано или поздно будет передан не тот объект, который ожидаем

Это элементарно контролируется сигнатурой и/или sizeof.

И вообще меня неправильно поняли - я не предлагаю тащить в С концепции С++, а лишь провожу аналогии - это все там и так есть, просто приглядитесь повнимательнее.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 01:18
Рейтинг@Mail.ru


Страница сгенерированна за 0.01502 секунд с 7
ELECTRONIX ©2004-2016