Форум: "Потрепаться";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];
ВнизПро глобальные переменные Найти похожие ветки
← →
TButton © (2004-04-08 18:45) [0]а что, это действительно моветон? у меня, например, в одной проге была глобальная переменная users: array... да, и был отдельный юнит с функциями для работы с этим массивом (преимущественно - поиск и выдирание сведений о конкретном юзере) соответсвенно модуль с утилитами юзал Unit1.
или, например, есть у меня глобальная переменная mode и один таймер, котрый в заисимости от значения этого mode - выполняет те или иные операции.
вот сижу и не понимаю, а что в этом плохого-то?
← →
Тимохов © (2004-04-08 18:48) [1]Это разговор в продолжение какого-то другого?
← →
TButton © (2004-04-08 18:50) [2]нет. это я просто давно не могу понять, почему некоторые люди плюются в сторону глобальных переменных... типа антиглобалисты...
← →
Гаврила (2004-04-08 18:51) [3]ну вообще-то даже главная форма приложения сразу автоматически создается как глобальная переменнаая, то есть однозначно сказать ,что это моветон, нельзя.
Для каждого случая надо принимать отдельное решение
Если она используется как способ передачи параметра между процедурами, это, имхо, плохо (например)
← →
TButton © (2004-04-08 18:56) [4]>Если она используется как способ передачи параметра между >процедурами, это, имхо, плохо (например)
обоснуйте, если не затруднит, бо я так делал, но ничего плохого не заметил.
← →
Тимохов © (2004-04-08 18:58) [5]Я вот тоже плююсь - у меня их вообще нет. Наверное ни одной. Естесно кроме тех, которые идут из vcl модулей. Своих нет.
Вернее так - есть но только под implementaion, в interface нет, как и свободный функций...
Почему так?
Сложно объяснить. Такова моя жизненная позиция. Если нужно делать гл. перем, то через классовые методы некого класса, который хранит значения под implementation.
← →
Гаврила (2004-04-08 19:00) [6]>>TButton © (08.04.04 18:56) [4]
Процедура A вызывает процедуру B, которая в свою очередь вызывает либо C либо Д в зависимости от условий, которые в свою очередь... и так далее.
И каждая из них может менять значение глобальной переменной.
ПРоцедура С изменила ее значение ,а процедура А об этом "забыла"...
ТО есть достаточно просто запутаться и насажать багов
← →
Тимохов © (2004-04-08 19:01) [7]
> TButton © (08.04.04 18:56) [4]
это сложно объяснить, также как сложно объяснять высокопоставленному непрограммисту, что делать единственным средством вывода отчетов в программе excel нельзя - "Работает же ведь!".
← →
TButton © (2004-04-08 19:02) [8]>interface нет
а если нужен обмен данными между модулями? каждый раз передавать ссылку на данные?
← →
Тимохов © (2004-04-08 19:03) [9]
> >interface нет
> а если нужен обмен данными между модулями? каждый раз передавать
> ссылку на данные?
так точно...
← →
TButton © (2004-04-08 19:04) [10]>достаточно просто запутаться и насажать багов
ну знаете ли... я достаточно хорошо представляю себе структуру своей программы, а если что плохо представляю - можно на бумаге набросать, поэтому у меня весь стол бумагами завален, зато в уме полная ясность что где и как меняется.
← →
TButton © (2004-04-08 19:06) [11]>так точно...
вариант конечно, опять же повышается модульность и взаимная независимость...
← →
Тимохов © (2004-04-08 19:08) [12]
> TButton © (08.04.04 19:04) [10]
> >достаточно просто запутаться и насажать багов
>
> ну знаете ли... я достаточно хорошо представляю себе структуру
> своей программы, а если что плохо представляю - можно на
> бумаге набросать, поэтому у меня весь стол бумагами завален,
> зато в уме полная ясность что где и как меняется.
Программа программе рознь.
Пусть ты пишешь прогу в 2000 строк. Представь, что она разрослась до 2тыс строк и вас программеров уже 3. Вот тут-то все и начнется...
← →
TButton © (2004-04-08 19:11) [13]>Представь, что она разрослась до 2тыс строк и вас программеров
>уже 3. Вот тут-то все и начнется...
поэтому я предпочитаю работать один =) а 2 тысячи не предел.
← →
Думкин © (2004-04-08 19:20) [14]> [13] TButton © (08.04.04 19:11)
2 тысячи - да, но 200000 один человек поддерживать будет на грани помешательства или гениальности, если будет только заваленными бумагами ориентироваться и не только ими.
Глобальные использовать можно, но зачем плодить сущности - если они лишние?
А если не лишние- то ради бога.
← →
Тимохов © (2004-04-08 19:21) [15]Не знаю кем и где ты работаешь.
Но для хозяина конторы такой способ опасен. Т.к. перенять твой продукт другому будет намного сложнее в случае использвания глоб. перем.
Если ты работаешь на себя - дело твое.
Но учти, что в коллективе придется переучиваться.
← →
Тимохов © (2004-04-08 19:20) [16]Не знаю кем и где ты работаешь.
Но для хозяина конторы такой способ опасен. Т.к. перенять твой продукт другому будет намного сложнее в случае использвания глоб. перем.
Если ты работаешь на себя - дело твое.
Но учти, что в коллективе придется переучиваться.
← →
TButton © (2004-04-08 19:24) [17]200000
ниразу не видел. модули они же ведь и нужны чтоб упростить написание программы. я например использую VCL, т.е. не явно, но моя программа состоит из.... дофига строк, однако, это пока не отразилось на моем психическом здоровии.... разве что чуть-чуть...
← →
Style © (2004-04-08 19:32) [18]
> обоснуйте, если не затруднит, бо я так делал, но ничего
> плохого не заметил.
Да хотя бы потому что глобальная переменная - она глобальная переменная и ее можно изменить в любой части документа когда это нужно или когда это не нужно. Вот если, как сказано выше, кода на 200000 строк, то вероятность того что ты можешь изменить ее когда не нужно достаточно большая. Соответсвенно разобраться в таком коде и найти ошибку будет не так легко. Поэтому пределы видимости переменных лучше ограничивать.
← →
Думкин © (2004-04-08 19:33) [19]> [17] TButton © (08.04.04 19:24)
Знаете, ведь и строки строкам рознь. Книжечку тут читал недавно - если по строкам, то самые непродуктивные - американцы. В среднем они пишут меньше строк чем коллеги из других стран. Но чей код эффективней?
200000 - этоо много. Ведь вопрос - каких. Вот цитата:
"Разработка программного обеспечения для системы управления огнем истребителя F-16 обошлась в 85 млн. долларов. Объем программного обеспечения составил 236000 строк кода." (с)
Там и про объемы есть. И про бумажки на столе.
← →
TButton © (2004-04-08 19:40) [20]>Но чей код эффективней?
чей?
← →
Игорь Шевченко © (2004-04-08 20:23) [21]Можно использовать глобальные переменные, коран не запрещает.
Можно писать несколько операторов в одной строке, молнией никто с небес не поразит.
Просто с помощью объектно-ориентированного подхода программировать удобнее. На всех, практически, этапах жизненного цикла программы(проекта).
А объектно-ориентированый подход говорит, что данные, служащие для связи процедур или, в худшем случае, методов классов, это моветон :) Потому что, согласно тому же подходу, не инкапсулированные в объекты с методами их обработки, не имеют особого смысла. Это теория. А с точки зрения практики, неудобно отслеживать все точки взаимодействия с ними, неудобно, если случится так, что они окажутся зависимыми друг от друга (а так чаще всего и бывает), дублировать код, отслеживающий эту зависимость, и т.д.
С точки зрения теории - нехорошо, с точки зрения практики, неудобно, так зачем же их использовать сверх необходимости ?
← →
Гаврила (2004-04-08 20:32) [22]>>Тимохов © (08.04.04 18:58) [5]
насчет того, что процедур нет как свободных функций, это имхо, перебор. По сути вызов классовой функции отличается только более длинным синтаксисом (+ ClassName).
Обратимся к модулям от борланда - там есть свободные функции.
И читаемость кода типа TFileUtils.ExtractFileName будет ниже
← →
Юрий Зотов © (2004-04-08 20:48) [23]IMHO, одна из главных сторон искусства практического программирования как раз и состоит в таком сочетании процедурного подхода и ООП, глобальных переменных и "прозрачности" всех мест их использования
(и пр., и пр.), при котором код оптимален, безопасен, понятен, легко читаем и легко отлаживаем.
И если следовать этому принципу, то окажется, что глобальные переменные из кода либо исчезнут вообще, либо их останется ровно столько, сколько минимально необходимо. Не больше.
← →
Игорь Шевченко © (2004-04-08 20:51) [24]Гаврила (08.04.04 20:32)
> И читаемость кода типа TFileUtils.ExtractFileName будет
> ниже
А TFile.ExtractName ? :)
← →
panov © (2004-04-08 21:28) [25]Использую глобальные переменные для определения глобальных настроек, параметров в программе, которые используются во многих модулях.
Пока не заметил, чтобы это влияло как-то на количество ошибок и легкость чтения кода...
Ничего предосудительного не вижу в использовании глобальных переменных.
Следование догмам - не лучшая позиция...
← →
Nous Mellon © (2004-04-08 21:31) [26]В первых моих прогах была куча глобальных переменных - после изучения ООП никогда и ни одной..
← →
Игорь Шевченко © (2004-04-08 21:44) [27]panov © (08.04.04 21:28)
А я использую класс TSettings "для определения глобальных настроек, параметров в программе, которые используются во многих модулях", особенно после того, как заметил, что ряд переменных используется один и тот же в разных программах, при этом способ хранения их в реестре один и тот же :)
← →
panov © (2004-04-08 22:01) [28]>Игорь Шевченко © (08.04.04 21:44) [27]
Хорошая мысль, однако-)
Беру на вооружение-)
← →
nikkie © (2004-04-08 22:05) [29]экземпляр TSettings - глобальная переменная?
← →
vuk © (2004-04-08 22:09) [30]to nikkie © (08.04.04 22:05) [29]:
>экземпляр TSettings - глобальная переменная?
Тут рядом ветка была. Синглетоны обсуждались. :o)
← →
panov © (2004-04-08 22:11) [31]>nikkie © (08.04.04 22:05) [29]
экземпляр TSettings - глобальная переменная?
Конечно-)
Но зато можно скрыть реализацию чтения и сохранения параметров, например, в ini-файле.
Мне кажется, очень удобно будет обращаться так:PathData := MySettings.Value("MainSection","PathData");
MySettings.Value("MainSection","PathData") := PathData;
-)
← →
Anatoly Podgoretsky © (2004-04-08 22:23) [32]Игорь Шевченко © (08.04.04 21:44) [27]
Класс удобен когда надо сделать контролируемое поведение, например не просто прочитать или присвоить значение, а при этих действия выполнчить какие то скрытые действия, а обращение должно выглядеть как к переменной, достоаточно будет оформить как свойство и иметь полный контроль с возможностью легкой модификации. Если же этого нет то переменные для настроек не лучше и не хуже.
← →
nikkie © (2004-04-08 22:25) [33]>vuk
>Тут рядом ветка была. Синглетоны обсуждались. :o)
неужто? пишем синглтон и каждый раз пишем TSettings.Create только ради того, чтобы глобальных переменных не было? :))
>panov
>Мне кажется, очень удобно будет обращаться так:
ты немного подумаешь, поймешь, что для разных параметров типа Integer, String, Boolean придется написать свою версию Value, начнешь писать и задумаешься, не лучше бы сделать было по-другому.
← →
panov © (2004-04-08 22:34) [34]>nikkie © (08.04.04 22:25) [33]
ты немного подумаешь, поймешь, что для разных параметров типа Integer, String, Boolean придется написать свою версию Value, начнешь писать и задумаешься, не лучше бы сделать было по-другому.
Не обязательно.
1. Можно сделать параметры типа Variant
2. Можно перегрузку сделать(overload)
← →
Игорь Шевченко © (2004-04-08 22:35) [35]Anatoly Podgoretsky © (08.04.04 22:23)
Или иметь возможность наследования :)
← →
vuk © (2004-04-08 22:36) [36]to nikkie © (08.04.04 22:25) [33]:
>пишем синглтон и каждый раз пишем TSettings.Create
Можно и написать. Но если лень, можно и дополнить класс функцией типа такой:
class function GetInstance: TSettings;
:o)
До кучи еще добавлю, что у меня в последнее время глобальные данные собираются в классы с названиями типа TEnvironment, и делаются классовые методы доступа.
← →
Gero © (2004-04-08 23:09) [37]
> у меня в последнее время глобальные
> данные собираются в классы с названиями типа TEnvironment
Имхо, идеально.
То есть глобальная переменная будет всегда только одна(не считая переменных VCL).
← →
nikkie © (2004-04-08 23:11) [38]>собираются в классы
в синглтоны, надеюсь? :)
а то где же хранить данные, к которым обращаются классовые методы - не в глобальных же переменных :))
← →
Gero © (2004-04-08 23:16) [39]
[38] nikkie © (08.04.04 23:11)
> не в глобальных же переменных
Именно в глобальной переменной!
Представь, как это удобно.
Создал один TEnvironment на приложение, а там уже храни что угодно.
← →
Style © (2004-04-08 23:26) [40]
> а там уже храни что угодно.
Главное это что угодно использовать когда нужно. Иначе такая путанитца может получиться.
← →
nikkie © (2004-04-08 23:27) [41]>Представь, как это удобно.
представляю. берем TEnvironment, принимаем гениальное решение сделать его максимально гибким, разрешить хранить в нем не только стандартные типы, но и любые записи и классы, и, воспользовавшись идеей panov-а, делаем метод доступа
TEnvironment.GetValue(ValueName: String): Variant;
получаем пример того, как хорошую идею можно превратить в кошмар на улице вязов. прошу прощения за некоторое утрирование.
← →
Gero © (2004-04-08 23:31) [42]
> [41] nikkie © (08.04.04 23:27)
Да нет, варианты здесь ни к чему.
>Можно перегрузку сделать(overload) - это больше подойдет.
Да думаю лучше у vuk"a спросить, как он это реализовывает.
← →
nikkie © (2004-04-08 23:42) [43]>Можно перегрузку сделать(overload) - это больше подойдет.
нельзя сделать перегрузку, изменив только тип возвращаемого значения.
но в общем-то я не про то... практика - критерий истины (с) В.И.Ленин. пробуй - если жить станет легче, то значит такая техника имеет право на существование и ее надо использовать. а если жить легче не стало, но ты считаешь что так делать надо, потому что круто, когда "глобальная переменная будет всегда только одна", то наследники твоего кода проклянут тебя.
← →
Игорь Шевченко © (2004-04-09 00:14) [44]
> но ты считаешь что так делать надо, потому что круто
Это неправильный путь. Меньше всего хотелось бы видеть использование каких-либо приемов программирования именно по этой причине.
Всякий овощ приносит пользу, будучи употребленным в нужное время в нужном месте.
Мне, кстати, в свое время очень помогла взглянуть свежим взглядом на некоторые вещи книжка Мартина Фаулера: "Рефакторинг или улучшение существующего кода". Если выбросить из нее весь XP-шный стиль, и вдумчиво переработать рекомендации, очень неплохой источник информации, почему та или иная конструкция имеет право на существование, и в чем ее плюсы/минусы/отличия от других конструкций.
← →
Gero © (2004-04-09 00:25) [45]
> [43] nikkie © (08.04.04 23:42)
> но ты считаешь что так делать надо, потому что круто
Ошибаешься. Я никогда не делаю что-либо "потому что круто".
Хм, скажи, чем будет плохо если все глобальные переменные запихнуть в один класс?
>то наследники твоего кода проклянут тебя
Объясни, может я чего-то не понимаю?
← →
nikkie © (2004-04-09 00:55) [46]блин... я дико прошу прощения. потерялось слово "если"
... но если ты считаешь ...
>Хм, скажи, чем будет плохо если все глобальные переменные запихнуть в один класс?
плохого я не вижу. впрочем и особых преимуществ тоже. только осознание того, что "все правильно сделал" (с) реклама. это если сделать
gSettings.VarName вместо gVarName.
а вот если сделать так: gSettings.GetValue("VarName"), то минусы имхо очевидны. разумеется, я говорю о конечном наборе заранее определенных разнотипных переменных, а не массива однотипных.
>>то наследники твоего кода проклянут тебя
>Объясни, может я чего-то не понимаю?
попробуй работать с глобальными переменными так, как предложил [31] panov - после этого тебе не захочется проклясть автора этой технологии?
>Игорь Шевченко
>Всякий овощ приносит пользу, будучи употребленным в нужное время в нужном месте.
за сие и ратую :))
во избежание молотьбы воды в ступе - может вы с vuk-ом приведете пример, как именно устроены ваши классы для хранения настроек?
← →
Gero © (2004-04-09 01:08) [47]
> nikkie © (09.04.04 00:55)
> блин... я дико прошу прощения. потерялось слово "если"
> ... но если ты считаешь ...
Ааа, сразу бы так, а то я думаю: что за наезды :))
> попробуй работать с глобальными переменными так, как предложил
> [31] panov - после этого тебе не захочется проклясть автора
> этой технологии?
Да уж.
> nikkie
#ifdef личная переписка & offtop
Ты почту не проверяешь, тебе некогда или просто в облом мне писать?
#endif
← →
nikkie © (2004-04-09 01:12) [48]>Gero
не разобрался с проблемой пока.
← →
Piter © (2004-04-09 01:12) [49]Игорь Шевченко (08.04.04 21:44) [27]
А я использую класс TSettings
Ни фига себе... вообще-то это я использую класс TSettings... ой, точнее запись
← →
Vuk © (2004-04-09 01:53) [50]to nikkie:
>в синглтоны, надеюсь? :)
Сам по себе Envirobment может быть синглетоном или не быть им (если используются исключительно методы класса).
>а то где же хранить данные, к которым обращаются классовые
>методы - не в глобальных же переменных :))
Если это классовые методы, то данные, понятное дело, хранятся в переменных. Но глобальными они не будут (будет видимость в пределах раздела реализации модуля) и возможности изменить их кроме как через методы TEnvironment не будет.
>делаем метод доступа
>TEnvironment.GetValue(ValueName: String): Variant;
А вот так я делать пожалуй буду только в том случае, если класс TEnvironment должен будет предоставлять сервис на манер ini-файлов. В остальном же все обычно делается несколько иначе. Если нужно получать какое-то значение (простого или составного типа - неважно) то заводятся соответствеющие методы, которые будут работать с этими данными и только с ними а результат работы будет строго типизирован. Для большей же гибкости могут создаваться дополнительные классы управления конфигурацией (к примеру DatabaseConfigurationManager, UserConfigurationManager и т.п.) и TEnvironment содержит методы, которые возвращают ссылки на экземпляры этих классов. Это позволяет не загромождать TEnvironment множеством методов доступа к конкретным данным.
← →
Думкин © (2004-04-09 07:16) [51]TButton © (08.04.04 19:40) [20]
>Но чей код эффективней?
чей?
Ну примерно так - программист в США в среднем пишет около 7700 строк кода в год, а в других странах - 16700 строк. Но если использовать понятие "функциональная точка", то производительность у первых 63,1 фт, а у вторых менее 30. Это из той же книги, не мое. Но я думаю смысл ясен и объяснение можно найти. Вы о СММ или CBP слышали?
> Игорь Шевченко © (08.04.04 21:44) [27]
> panov © (08.04.04 21:28)
> А я использую класс TSettings "для определения глобальных
> настроек,
Да, я тоже его давно внедрил, когда работал с Дельфи. Это было намного удобней, чем всякий раз определять глобальные переменные и спец.процедуры обработки значений этих переменных.
← →
Polevi © (2004-04-09 08:16) [52]>Anatoly Podgoretsky © (08.04.04 22:23) [32]
TSettings=class(TPersistent) удобен тем что его можно сериализовать
для добавления нового парметра настроек достаточно добавить published св-во
← →
TUser © (2004-04-09 08:20) [53]Ничего в них нет плохого. Иногда бывает полезно назначить некоторые флаги, которые нужны для модификации работа всех процедур модуля. И если нет желания пихать все это в класс ради добавления одного-двух новых свойств - тогда гл. пер. в interfac"е рулят.
← →
int64 (2004-04-09 10:26) [54]TButton ©
Позвольте несколько ваших слов:
> в одной проге была глобальная переменная users: array...
> да, и был отдельный юнит с функциями для работы с этим массивом
> (преимущественно - поиск и выдирание сведений о конкретном
> юзере)
...
> а если нужен обмен данными между модулями? каждый раз передавать
> ссылку на данные?
...
> модули они же ведь и нужны чтоб упростить написание программы
Создается впечатление, что вы разделяете логику программы на модули, там, где целесообразнее было бы рисовать классы.
Когда вы реально вникнете в ООП, у вас такие вопросы, как сабж даже появляться не будут.
Мой совет: избавляйтесь от рудиментов модульно-функционального программирования.
← →
DiamondShark © (2004-04-09 11:10) [55]А у меня в каждой программе куча глобальных переменных: Application, Screen, Mouse...
← →
Странник © (2004-04-09 11:31) [56]> int64 [54]
> Мой совет: избавляйтесь от рудиментов модульно-функционального
> программирования
а зачем?
мне вот больше импонирует точка зрения Юрий Зотов © (08.04.04 20:48) [23]
← →
int64 (2004-04-09 12:06) [57]Не думаю , что Юрий Зотов в своём ИМХО подразумевал глобальную переменную со списком функций над ней в отдельном модуле. Когда может понадобиться наследование и виртуальные методы над этим модулем.
Я тоже не отрицаю процедурное программирование. Но всему свое место.
← →
Anatoly Podgoretsky © (2004-04-09 12:28) [58]ЮЗ подразумевал одно - подумать и применить нужное
← →
Vuk © (2004-04-09 12:30) [59]to int64 (09.04.04 10:26) [54]:
>Мой совет: избавляйтесь от рудиментов модульно-функционального
>программирования.
Чего-чего? Модульно-функционального? Во-первых модульность не трожьте, а во-вторых вы функциональное программирование с процедурным не путаете?
← →
int64 (2004-04-09 12:33) [60]Vuk © (09.04.04 12:30) [59]
Ну понятно, что оговорился.
← →
Vuk © (2004-04-09 12:36) [61]to int64 (09.04.04 12:33) [60]:
>Ну понятно, что оговорился.
Понятно. :o) Но модульность все равно не трожьте, она есть рулез. :o)
← →
Матлабист (2004-04-09 15:31) [62]Про многопоточность никто не вспоминал?
← →
Wizard_Ex © (2004-04-09 16:45) [63]По поводу класса TSettings
Написать такой класс как TSettings по своему вкусу не составляет особого труда, зато польза от этого мне кажется немаленькой,
Я не против использования глобальных переменных - если оно необходимо, почему бы и нет, но в достаточно большом проекте ИМХО лучше использовать спец. класс.
Игорь Шевченко © - я ЗА.
И также по поводу:
> panov © (08.04.04 22:11) [31]
> Мне кажется, очень удобно будет обращаться так:
>
> PathData := MySettings.Value("MainSection","PathData");
> MySettings.Value("MainSection","PathData") := PathData;
> -)
Можно еще просто не использовать секции и хранить все вместе, может не удобно - инифайл будет свалкой, но обращаться можно еще и так - визуально смотриться проще и не надо мучаться вспоминать что и где, в какой секции, лежит:
PathData:=MySettings["PathData"];
MySettings["PathData"]:=PathData;
Для этого класс должен иметь свойство типа
property Settings[const Name: String]: Variant read GetSettings write SetSettings; default;
Variant наверно подойдет для всех нужд по хранению настроек.
Все остальное скрывается внутри класса и никто не морочит себе голову лишней возней с сохранением и т.д. и т.п.
← →
Wizard_Ex © (2004-04-09 18:37) [64]И кстати, почему именно ини-файл, может хочется кому в реестре данные хранить или и там и там, или файл хитрозашифрованный создать.
Свобода выбора и польза налицо
← →
TButton © (2004-04-09 19:36) [65]re 54, 57
Просто я обрисовал ситуацию в двух словах. Побоялся, что запинают. А если подробнее то дело обстояло так. users: array of TStringList; это во-первых, в MainUnit список юзеров загружался, обрабатывались события сокетов, сообщения от юзеров, результат этой обработки - изменение содержимого аккаунтов, а юнит с утилитами просто упрощал обработку, т.е. я мог просто не заморачиваясь вызвать функцию UserName(VNUM) и т.д. и т.д.
а насчет классов, знаете, мне кажется я до них еще не дорос. у меня только начинает складываться общее представление о них. сам по старинке пользуюсь object"ами, к коим с таким трудом приучился в Паскале.
← →
YurikGl © (2004-04-09 19:51) [66]>>Ну примерно так - программист в США в среднем пишет около 7700 строк кода в год, а в других странах - 16700 строк.
Видимо, программисты в других странах пишут на ASM
:)
← →
Knight © (2004-04-09 20:17) [67]По своему скромному опыту скажу... Есть опраданные случаи использования глобальных переменных, но их круг, в основном, ограничен глобальными же настройками, которые используются сразу в нескольких модулях и при этом зачастую вообще не меняют своих значений при работе программы. Но в любом случае они должны иметь специальные имена, чтобы было легче отследить места их использования, например, иметь какую-то приставку (G_DBPath) или группироваться в отдельный тип (типа, TSettings=record, class, object - кому, что ближе)
Но самой опасной остаётся глобальная переменная User:TUser;
за этой нужен глаз да глаз, а то можно таких глюков наловить, что мало не покажется :)
← →
Anatoly Podgoretsky © (2004-04-09 20:21) [68]С этим просто TRestrictedUser = class(TUser)
← →
Anatoly Podgoretsky © (2004-04-09 20:23) [69]TUser должен быть базовым классом с абстрактными методами.
← →
Vuk © (2004-04-09 20:28) [70]Мой коллега, который в нашей софтине делал подсистему печати отчетов на основе FastReport постоянно материт этот генератор отчетов за стиль в котором он написан. Главные проблемы создают глобальные переменные.
← →
Knight © (2004-04-09 20:39) [71][68] Anatoly Podgoretsky © (09.04.04 20:21)
Как не назови, а доверять этому классу (даже ограниченному) низя ни при каких обстоятельствах... рубить, надо, на корнь любую самодеятельность, шаг вправо, шаг влево - стрелять без предубеждений :)
← →
Anatoly Podgoretsky © (2004-04-09 21:13) [72]Vuk © (09.04.04 20:28) [70]
Не единственная, не знаю как в новых версиях, но было еще более неприятный моментtry
обработка
except
end
← →
vuk © (2004-04-09 21:24) [73]to Anatoly Podgoretsky © (09.04.04 21:13) [72]:
Ну обычно там еще хлеще, то есть вообще без всякой обработки исключений. Типа того:
st := TMemoryStream.Create;
//что-то сделали с потоком
st.Free;
← →
Knight © (2004-04-09 21:28) [74]
> [72] Anatoly Podgoretsky © (09.04.04 21:13)
> try
> обработка
> except
> end
Действительно неприятная весчь... поубывав бы
← →
panov © (2004-04-09 21:47) [75]Ну вот... к вопросу о хранении глобальных параметров-)
Наклепал немного кода.
{
Класс для хранения настроек программы в ini-файле.
}
unit uApSettings;
interface
uses
windows,Sysutils;
type
TRecParam = record
rSec,
rNameValue: PChar;
rParamData: Variant;
end;
TSettings = class(TObject)
private
FIniName: String;
FParams: array of TRecParam;
FSectionName: String;
procedure FSetIniName(aIniName: String);
procedure RecInit(var aRec: TRecParam;aSec,aNameValue: String;aValue: Variant);
procedure RecFree(var aRec: TRecParam);
procedure AddRecToFParams(aNameValue: String; aValue: Variant);
procedure ClearFParams;
procedure LoadParams;
function FGetParam(aNameValue: String):Variant;
procedure FSetParam(aNameValue: String;aValue: Variant);
protected
public
constructor Create(aIniName:String="");
destructor Destroy;override;
property IniName: String read FIniName write FSetIniName;
property Params[aNameValue: String]: Variant read FGetParam write FSetParam;
end;
var
AppSettings: TSettings;
implementation
constructor TSettings.Create(aIniName:String="");
var
Len: Integer;
begin
if Assigned(AppSettings) then
raise Exception.Create("Create TSettings: Error, object already exists");
if FIniName = "" then
begin
FIniName := ParamStr(0);
Len := Length(FIniName);
FIniName[Len] := "i";
FIniName[Len-1] := "n";
FIniName[Len-2] := "i";
end
else FIniName := aIniName;
FSectionName := "AppParameters";
LoadParams;
end;
destructor TSettings.Destroy;
begin
ClearFParams;
AppSettings := nil;
inherited;
end;
procedure TSettings.FSetIniName(aIniName: String);
begin
ClearFParams;
FIniName := aIniName;
LoadParams;
end;
procedure TSettings.RecInit(var aRec: TRecParam;aSec,aNameValue: String; aValue: Variant);
var
Len: Cardinal;
begin
Len := Length(aSec);
try
ReallocMem(aRec.rSec, Len+1);
aRec.rSec[Len] := #0;
Move(aSec[1],aRec.rSec^,Len);
Len := Length(aNameValue);
ReallocMem(aRec.rNameValue, Len+1);
aRec.rNameValue[Len] := #0;
Move(aNameValue[1],aRec.rNameValue^,Len);
aRec.rParamData := aValue;
except
raise Exception.Create("TSettings: RecInit. Unknown error :-(");
end;
end;
procedure TSettings.RecFree(var aRec: TRecParam);
begin
try
if aRec.rSec<>nil then
begin
FreeMem(aRec.rSec);
aRec.rSec := nil;
end;
if aRec.rNameValue<>nil then
begin
FreeMem(aRec.rNameValue);
aRec.rNameValue := nil;
end;
except
raise Exception.Create("TSettings: RecFree. Unknown error :-(");
end;
end;
procedure TSettings.AddRecToFParams(aNameValue: String; aValue: Variant);
var
Len: Cardinal;
begin
Len := Length(FParams);
SetLength(FParams,Len+1);
RecInit(FParams[Len],FSectionName,aNameValue,aValue);
end;
procedure TSettings.ClearFParams;
var
i: Integer;
begin
for i := 0 to Length(FParams)-1 do RecFree(FParams[i]);
SetLength(FParams,0);
end;
procedure TSettings.LoadParams;
var
i: Integer;
buf: array of Char;
Len,LenRes: Integer;
Names,Params: array of String;
s: String;
p: PChar;
begin
Len := 8192;
LenRes := 0;
SetLength(buf,Len);
repeat
if LenRes=Len-2 then
begin
Len := Len*2;
SetLength(buf,Len);
end;
LenRes := GetPrivateProfileSection(PChar(FSectionName),@buf[0],Len,PChar(FIniName));
until LenRes<>Len-2;
if LenRes=0 then
begin
SetLength(buf,0);
Exit;
end;
p := @buf[0];
SetLength(Names,1);
SetLength(Params,1);
for i := 0 to Length(Buf)-2 do
begin
if buf[i]="=" then
begin
SetLength(Names[Length(Names)-1],@buf[i]-p);
Move(p^,Names[Length(Names)-1][1],@buf[i]-p);
p := Pointer(Cardinal(@buf[i])+1);
SetLength(Names,Length(Names)+1);
Continue;
end;
if buf[i]=#0 then
begin
SetLength(Params[Length(Params)-1],@buf[i]-p);
Move(p^,Params[Length(Params)-1][1],@buf[i]-p);
SetLength(Params,Length(Params)+1);
p := Pointer(Cardinal(@buf[i])+1);
if buf[i+1]=#0 then break;
end;
end;
SetLength(buf,0);
for i := 0 to Length(Names)-1 do AddRecToFParams(Names[i],Params[i]);
SetLength(Names,0);
SetLength(Params,0);
end;
function TSettings.FGetParam(aNameValue: String):Variant;
var
i: Integer;
begin
Result := Variant(0);
for i := 0 to Length(FParams)-1 do
begin
if FParams[i].rNameValue=aNameValue then
begin
Result := FParams[i].rParamData;
break;
end;
end;
end;
procedure TSettings.FSetParam(aNameValue: String;aValue: Variant);
var
i: Cardinal;
isFound: Boolean;
Rec: TRecParam;
StrParam: String;
Ret: Boolean;
begin
isFound := False;
for i := 0 to Length(FParams)-1 do
begin
if FParams[i].rNameValue=aNameValue then
begin
isFound := True;
FParams[i].rParamData := aValue;
Rec := FParams[i];
break;
end;
end;
if not isFound then
begin
AddRecToFParams(aNameValue,aValue);
Rec := FParams[Length(FParams)-1];
end;
StrParam := Rec.rParamData;
if StrParam="" then
Ret := WritePrivateProfileString(PChar(FSectionName),
Rec.rNameValue,
nil,
PChar(FIniName))
else
Ret := WritePrivateProfileString(PChar(FSectionName),
Rec.rNameValue,
PChar(StrParam),
PChar(FIniName));
if not Ret then
raise Exception.Create("TSettings: Error. Value not saved");
end;
initialization
AppSettings := TSettings.Create;
finalization
AppSettings.Free;
end.
← →
Игорь Шевченко © (2004-04-09 22:08) [76]panov © (09.04.04 21:47)
1) Зачем так сложно ?
2) Предположим усложненный вариант (реальная задача): Часть настроек хранятся в централизованном хранилище, для всех пользователей (например, в базе данных), часть настроек хранится в реестре на компьютере у каждого пользователя (с определенным ключом). Классом с набором настроек в программе удобно пользоваться одним.
Пути решения ?
← →
Игорь Шевченко © (2004-04-09 22:15) [77]
> if FIniName = "" then
if aIniName = "" then
← →
panov © (2004-04-09 22:17) [78]>Игорь Шевченко © (09.04.04 22:08) [76]
При написании этого класса я не рассчитывал на БД.
Потому и решение было таким.
а для поставленной задачи решение может быть таким:
1. В БД хранятся параметры, общие для всех, параметры по умолчанию(шаблоны) - те, которые пользователи хранят в реестре локально.
Те настройки, которые не изменяются, редактирует только администратор.
2. Далее принцип такой же, как мне кажется.
← →
panov © (2004-04-09 22:19) [79]>Игорь Шевченко © (09.04.04 22:15) [77]
Точна! Первый жук-)
← →
Германн © (2004-04-09 22:36) [80]Раз глобальные переменные существуют, должен же из кто-то использовать.
© Писатель в детской курточке.
← →
Knight © (2004-04-10 15:14) [81]По сабжу...
Помните золотые слова: "Следует потреблять, но не злоупотреблять"
(С)Тайксейр и Пачеко "Delphi5: руководство разработчика":
← →
Polevi © (2004-04-10 19:44) [82]>panov
слишком сложно и ограничено
гораздо проще написать 2-фии - одна сохраняет TPersistent base object в xml с помощью RTTI, вторая восстанавливает
все
Страницы: 1 2 3 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];
Память: 0.71 MB
Время: 0.036 c