Когда можно использовать глобальную переменную

22

Итак, это действительно вопрос адвоката дьяволов.

Когда с глобальными переменными все в порядке, и если никогда, что бы вы использовали в качестве альтернативы?

Интересный побочный пример этого вопроса: чем общедоступное поле статического класса отличается от глобального?

ocodo
источник
5
Code Complete , 2-е издание, §13.3.
Джерри Гроб
1
Многопоточные приложения в значительной степени требуют глобальных переменных.
Аква
См. Software Coupling
PP.
4
@aqua В многопоточных приложениях глобальные переменные могут быть наиболее разрушительными. Все ненавидят сложную логику блокировки.
luiscubal
1
@JerryCoffin Если публикация ссылки в качестве ответа без цитирования соответствующего отрывка является плохой практикой, то и цитирование раздела книги без цитирования соответствующего отрывка. Особенно потому, что книги не так легко и легко доступны, как веб-страницы.
Брэден Бест

Ответы:

18

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

Единственный раз, когда я лично использую «глобальные» переменные в своем коде, в форме открытых статических полей, которые являются неизменяемыми. В этом случае нет необходимости беспокоиться о том, что значение может быть искажено другими частями программы, и, конечно, это намного лучше, чем иметь дюжину переменных с одинаковыми постоянными значениями в каждом классе.


источник
2
Я бы назвал неизменное поле константой .
aioobe
14

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

Anon.
источник
Вы бы использовали чистый глобальный для этого или публичный статический / синглтон?
ocodo
1
@Slomojo: Определенно не синглтон. В зависимости от ситуации, либо статика в классе конфигурации, либо простые глобальные переменные с префиксом CONFIG_или CFG_.
Анон.
+1 единственное изменение, которое я бы предложил, это сказать: «… подвержен ошибкам, передавая его каждому методу в любом другом классе». В противном случае это может быть ограничено в классе с тем, что служит - синглтон, я думаю.
Майкл Даррант
8

Исключая системы реального времени / встроенные системы, вы должны использовать глобальные переменные только для постоянных значений. Если вы чувствуете, что не можете решить свою проблему без них, вы, вероятно, делаете что-то не так.

Кроме того, обратите внимание на шаблон Singleton : он может обеспечить лучшее решение для глобальных переменных в тех ситуациях, когда вам нужно что-то для глобальной точки доступа.

Давор Адрало
источник
8
Я бы, вероятно, предложил избегать синглетонов.
ocodo
Я не утверждаю, что синглтоны великолепны, но я все же думаю, что они намного превосходят глобальные переменные.
Давор Адрало
Постоянные значения должны быть доступны только в той области / модуле, к которым они относятся. Константа TIMES_TO_ITERATE_THROUGH_THIS_PARTICULAR_LOOPотносится только к одному файлу / классу / разделу, где появляется «этот конкретный цикл».
Ктулху
1
Поля синглтона являются глобальными переменными, поэтому я не вижу никакой разницы.
Слёске
1
@Cthulhu позвольте мне процитировать себя: «в тех ситуациях, когда вам нужно что-то иметь глобальную точку доступа».
Давор Адрало
6

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

Еще один пример того, что я чувствую таким образом, посмотрите на использование mixins в Ruby.

btilly
источник
Какой пример (ы) вариантов использования вы бы предложили для этих вариантов использования глобалов?
ocodo
1
@Slomojo: Примером глобальных переменных, которые я не против, является использование @ARGV и $ _ в Perl. Я возражаю против использования глобалов для дешевой передачи параметров в подпрограммы.
до
5

Это все о пространствах имен.

Представьте на мгновение, что у всех в мире одинаковая фамилия. Какой беспорядок

(В Индии сикхи имеют одинаковую фамилию: Сингх - посмотрите)

Кристофер Махан
источник
6
Он используется , чтобы быть все о пространствах имен, но сейчас речь идет о безопасности потока.
Ден04
6
@ dan04 Речь идет об отсутствии отвратительного дизайна с жутким действием на расстоянии.
Том Хотин -
2
@Tom: Может быть, мы можем назвать это, насмешливо, "Квантовое программирование"
Кристофер Махан
4

Краткая версия: когда легче рассуждать о программе. Обычно случаи - это некий тип глобального состояния или статического ресурса, который широко используется.

Длинная версия: Том Хотин сказал: «с жутким действием на расстоянии» ... в этом и заключается проблема глобалов - вы должны знать, где он используется и как, или вы можете получить некоторые действительно странные и трудные для отслеживания ошибок. Местные жители - это не что иное, как стратегия уменьшения объема того, что программист должен понимать, чтобы рассуждать о программе.

Другая сторона проблемы с знанием того, где они используются, заключается в том, что вы можете получить дублирующиеся глобальные переменные - в этом случае все может стать действительно странным, так как большинство программ получает и устанавливает var1, в то время как в нескольких местах var2 используется для хранения. та же информация. Особенно, когда несколько человек работают над одним и тем же кодом. IDE могут быть полезны для поиска использования, снижающего стоимость глобальных переменных, но они ничего не делают для дубликатов.

Чем больше глобалов у вас есть, тем сложнее отслеживать, что с ними происходит. Их должно быть мало и далеко.

jmoreno
источник
В конечном итоге наличие изменчивых глобалов - довольно плохая идея. Единственное достойное исключение - при работе с очень жесткими аппаратными компонентами, такими как встроенное программирование. По крайней мере, кандидаты на глобальные переменные в обычном программировании должны быть разделены на статические члены классов или модулей, все, что может быть изменено, также должно рассматриваться как особый случай, вдвойне, при работе в многопоточной среде. Использование блокировок / фьючерсов / обещаний или другого метода обеспечения безопасности потоков / транзакций. - Поскольку никто не упомянул об этом, посмотрите на проблему столовых философов.
ocodo
1
Без сомнения, потоки могут усложнить работу с изменчивыми глобальными переменными, но вы можете получить ту же самую основную проблему из-за событий. Я согласен с предложением поставить подол в качестве статических членов и хотел бы пойти дальше и сказать, что в идеале они должны быть ЧАСТНЫМИ статическими членами.
Jmoreno
3

Два недостатка с глобальными и синглетонами - это тестируемость и возможность развертывания.

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

Что касается возможности развертывания, следует рассмотреть два случая. Во-первых, как будет жить ваш глобальный объект? Это в статической или динамической библиотеке? Если этот глобальный объект будет повторно использован для плагина, вы получите дополнительные копии? Во-вторых, что происходит, когда этот глобальный объект помещается в параллельное приложение? Это потокобезопасно?

В целом, я полагаю, эти причины означают, что глобалы и синглтоны используются исключительно в исключительных случаях.

smithco
источник
2

Разработка критических встроенных систем обычно включает использование глобальных переменных.

Размеры стека крошечные, все статически размещено ( malloc()запрещено), глобальные переменные скрыты за пределами библиотеки, к которой они принадлежат.

mouviciel
источник
0

В ужасной кодовой базе VB6, которая злоупотребляет глобальными кодами, как будто завтра не наступит, я виновен во введении нового:

Global CsExt As New TheAppBeingRewrittenInCSharpWhileVb6CodeIsStillBeingMaintained

Я думаю, что это один из немногих допустимых вариантов использования для глобального объекта.

Матье Гиндон
источник