Являются ли глобальные переменные плохими? [закрыто]

247

В C / C ++ глобальные переменные настолько плохи, насколько их считает мой профессор?

GEOCHET
источник
17
Я укушу на случай, если он попытается рассказать шутку ... "Насколько они плохи"?
Зак Скривена
13
Я думаю, что этот вопрос был довольно интересным! Разработка программного обеспечения все еще сталкивается с теми же старыми ловушками с самого начала, и программисты часто все еще не знают, что использование глобальных переменных, gotos, переменных с короткими именами НЕ является проблемой. Плохой код пишется каждый день без их использования. +1
Сильвен Родриг
69
Как мы можем ответить? Он не сказал нам, как плохо его профессор думает, что они. :)
Стив Фэллоуз
9
@Juan Mendes Я на 100% согласен с тобой! Проблема, о которой я говорил, заключается в том, что многие разработчики знают, что им не следует использовать глобальные переменные, но они просто не знают, почему! И, таким образом, я видел много больших программ, в которых каждая функция получила одну и ту же мегаструктуру, содержащую +100 полей - смотри, мама, без глобальных переменных! Та же проблема, что и у так называемых «хороших практик»: это хорошие практики в НЕКОТОРЫХ контекстах, а не во всех. Их использование МОЖЕТ создать неуправляемый код. Приветствия.
Сильвен Родриг
3
Существует очень мало хороших вариантов использования глобальных переменных. Одним из возможных, но дискуссионных вариантов использования может быть глобальный объект «конфигурации», который считывает файл конфигурации один раз при запуске.
Siler

Ответы:

257

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

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

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

Брайан Расмуссен
источник
10
Этот ответ действительно хорош. Объедините это с ответом «минимизируйте переменную область действия» stackoverflow.com/questions/357187/…
bobobobo
17
Замените «class» на «application» и «object state» на «global state», и вы получите точно такой же аргумент, чтобы не использовать переменные-члены (иначе поля) в классах. Реальный ответ - используйте их, когда это уместно.
Ян Голдби
2
Несколько (возможно, глупых) вопросов: 1) Если вы хотите узнать, какие функции читают и записывают эти переменные, не могли бы вы просто использовать функцию «найти» в редакторе, чтобы определить случаи, когда значения в этих переменных изменяются? 2) «Это можно сделать, ... пустая трата времени)». Можете привести пример? 3) «Если вы не полагаетесь на глобальные переменные, вам не нужно учитывать глобальное состояние». Я не понимаю, как это преимущество. Возможно, пример этого будет работать для меня.
Андрей
2
@ Бобобобо неработающая ссылка, можем ли мы получить скриншот от вас, пользователя 10k +?
noɥʇʎԀʎzɐɹƆ
3
@ noɥʇʎԀʎzɐɹƆ Вот, пожалуйста! i.imgur.com/RwRgJLZ.jpg
Матин Улхак
85

Важно помнить общую цель: ясность

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

Однако, как и многие правила, люди помнят правило, а не то, для чего предназначалось правило.

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

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

Том Вест
источник
8
Предложение использовать глобальные вместо передачи переменных является рецептом для того, чтобы сделать ваш код не пригодным для повторного использования и небезопасным для многопоточности
Хуан Мендес,
16
Предлагая глобальные переменные в правильных обстоятельствах, это рецепт более ясного и высокопроизводительного кода. «Передача» требует постоянного динамического распределения памяти, и это было бы глупо для чего-то, что должно быть глобальным, например глобального буфера для входящих данных сокета. Например, если у вас есть функция, которая читает Winsock recv (), зачем постоянно создавать и освобождать этот буфер в каждом вызове? Сделайте буфер глобальным. Несколько потоков не будут читать это в любом случае.
Джеймс
Просто любопытно, какая программа удваивает размер кода, передавая параметры, чтобы избежать глобальных переменных? По моему опыту, использование глобальных переменных может решить проблемы с экспозицией данных, но обычно есть дополнительная сложная логика, которую необходимо добавить, чтобы убедиться, что эти магические переменные ведут себя правильно.
user2167582
3
Если кто-то передает около 100 переменных, он не узнал, что такое объект. Использование ссылки на этот объект в худшем случае будет передавать указатель. Я бы сказал, что правило - это не только ясность, но и тестируемость, а использование неглобальных средств значительно облегчает тестирование.
UKMonkey
2
«Если кто-то передает около 100 переменных, значит, он не узнал, что такое объект». Договорились, но не весь мир является объектно-ориентированным. Моим личным примером удвоения размера кода была большая программа на Фортране, около 1986 года. Будучи только что окончившим университетским сотрудником, я «улучшил» ее, добавив около 30 параметров к каждому вызову, исключив все глобальные переменные. Затем отменил мое улучшение, когда я понял, что я сделал.
Том Вест
64

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

barneytron
источник
25
Это точно. Они как gotos, если вы не знаете, когда их использовать, то никогда не делайте.
Дэвид Холм
5
В моей нынешней компании они staticчасто используют глобальные переменные, язык C. Будучи ограниченным относительно небольшими единицами перевода, они начинают напоминать переменные класса объектов C ++.
Vorac
1
Статические переменные @Vorac не являются глобальными переменными, они являются локальными переменными. Глобальная переменная - это переменная, доступная повсюду в программе (отсюда и «глобальная», дух). Не следует путать с переменными области видимости файла , которые являются переменными, объявленными вне какой-либо функции. Переменная области статического файла не является глобальной переменной.
Лундин
1
Чтобы исправить себя program lifetime, file scope variables. И они становятся довольно глобальными, когда вы передаете указатель на переменную во внешний мир (что невозможно с автоматическими переменными) ..
Ворак
@ Лундин Я согласен, staticглобальные переменные имеют ограниченную область действия для одной и той же единицы перевода. Но у них есть время жизни до конца программы, как у любой глобальной переменной.
akhilesh1988
38

Глобальные переменные следует использовать только тогда, когда у вас нет альтернативы. И да, это включает в себя синглтоны. В 90% случаев глобальные переменные вводятся для экономии затрат на передачу параметров. И тогда происходит многопоточность / модульное тестирование / обслуживание кода, и у вас есть проблема.

Так что да, в 90% случаев глобальные переменные плохие. Исключения вряд ли будут замечены вами в ваши студенческие годы. Единственное исключение, которое я могу придумать, - это работа с глобальными объектами, такими как таблицы прерываний. Такие вещи, как соединение с БД, кажутся глобальными, но это не так.


источник
2
Единственным исключением, которое я видел в студенческие годы, были функции графического обратного вызова. В XWindows у мышиных обратных вызовов не было аргументов void * data, которые позволяли бы вам передавать произвольные куски состояния программы ... (не то, что это в конечном итоге НАМНОГО лучше, чем глобальное ...)
Брайан Постоу,
10
+1 за «Такие вещи, как соединение с БД, кажется глобальным, но это не так».
R .. GitHub ОСТАНОВИТЬ ЛЬДА
1
Таблицы прерываний не являются глобальными, по одному на процессор, но есть также один экземпляр вашей программы на процессор, поэтому он «отменяется».
user253751
1
Может ли кто-нибудь объяснить мне, почему соединения с БД не являются глобальными (и что может быть хорошей альтернативой)? Я всегда думал о связях как об одном из редких случаев, когда глобальные приемлемы.
Floella
33

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

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

Например, если у вас есть простая глобальная целочисленная переменная, которая используется в качестве перечислимого индикатора, который различные компоненты используют в качестве конечного автомата, и вы затем вносите изменение, добавляя новое состояние для нового компонента, вы должны затем проследить все остальные компоненты, чтобы гарантировать, что изменение не повлияет на них. Примером возможной проблемы может быть, если switchоператор для проверки значения глобальной переменной перечисления с caseоператорами для каждого из текущих значений используется в разных местах, и бывает, что некоторые switchоператоры не имеют defaultслучая для обработки Неожиданное значение для глобального внезапно вы имеете неопределенное поведение в отношении приложения.

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

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

Несколько проблем из глобальных переменных, которые нужно обойти

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

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

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

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

В некоторых случаях исходная цель приложения изменяется так, что глобальные переменные, которые предоставляли состояние для одного потока, модифицируются, чтобы позволить запускаться нескольким дублирующимся потокам. Примером может служить простое приложение, предназначенное для одного пользователя, использующее глобальные переменные для состояния, а затем из управления поступает запрос на добавление интерфейса REST, позволяющего удаленным приложениям выступать в качестве виртуальных пользователей. Итак, теперь вы столкнулись с необходимостью дублировать глобальные переменные и их информацию о состоянии, чтобы у одного пользователя, а также у каждого виртуального пользователя из удаленных приложений был свой собственный уникальный набор глобальных переменных.

Использование C ++ namespaceи structТехника для C

Для языка программирования C ++ namespaceдиректива является огромной помощью в уменьшении шансов столкновения имен. namespaceнаряду с classи различными ключевыми словами доступа ( private, protectedи public) обеспечивает большую часть инструментов, необходимые для инкапсуляции переменных. Однако язык программирования C не предоставляет эту директиву. Эта публикация потока стека, Пространства имен в C , предоставляет некоторые методы для C.

Полезный метод состоит в том, чтобы иметь одну резидентную область данных в памяти, которая определена как область, structкоторая имеет глобальную видимость, и в ней structесть указатели на различные глобальные переменные и функции, которые предоставляются. Фактические определения глобальных переменных задаются областью файла с использованием staticключевого слова. Если затем вы используете constключевое слово, чтобы указать, какие из них доступны только для чтения, компилятор может помочь вам обеспечить доступ только для чтения.

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

Однако, хотя namespaceили structметодика может помочь в управлении конфликтами имен, все еще существуют основные проблемы межкомпонентной связи, которые использование глобалов создает, особенно в современном многопоточном приложении.

Ричард Чемберс
источник
Это лучший пример объяснения, объясняющий все, что есть. Престижность!
johndoevodka
Ваш язык должен иметь кодовое правило, чтобы помешать вам использовать слишком много связывания классов.
Разработчик из Мельбурна
19

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

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

MSN
источник
19

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

См. Эту статью: Код ошибки алкотестера отражает важность исходного обзора

Были некоторые проблемы со стилем кода, которые были определены в обоих исследованиях. Одной из стилистических проблем, которые волновали рецензентов, было широкое использование незащищенных глобальных переменных . Это считается плохой формой, поскольку увеличивает риск того, что состояние программы станет несовместимым или что значения будут случайно изменены или перезаписаны. Исследователи также выразили некоторую обеспокоенность по поводу того факта, что десятичная точность не поддерживается последовательно во всем коде.

Бьюсь об заклад, те разработчики хотят, чтобы они не использовали глобальные переменные!

Casey
источник
6
Это был лучший смех за все время. Настоящий пример того, почему разработка с закрытым исходным кодом для получения прибыли - это плохо, а хороший пример глобальных изменений пошёл не так!
Злой Spork
Здесь установлено, что глобальные переменные рассматриваются с пренебрежением. Здесь нет ничего, что указывало бы на то, что глобальные переменные были настоящей проблемой в коде. SysTest сказал, что, хотя код «не был написан в соответствии с обычными рекомендациями по проектированию программного обеспечения», он все равно «надежно даст согласованные результаты испытаний». Так что никакого вреда от глобалов на самом деле не было задокументировано. На мой взгляд, они просто установили, что «ну, эти разработчики не практикуют ту же религию кодирования, что и остальной мир».
LionKimbro
19

Глобальные переменные так же плохи, как вы их делаете, не меньше.

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

Если вы посмотрите L.in.oleum , вы увидите язык, переменные которого являются исключительно глобальными. Это не масштабируется, потому что у всех библиотек нет другого выбора, кроме как использовать глобальные переменные.

Тем не менее, если у вас есть выбор и вы можете игнорировать философию программиста, глобальные переменные не так уж и плохи.

Как и Готос, если вы используете их правильно.

Большая «плохая» проблема заключается в том, что, если вы используете их неправильно, люди кричат, разбивается марс, и мир взрывается… или что-то в этом роде.

user54650
источник
17
Недооценивать проблемы использования глобалов для запутанного студента - не очень хорошая идея IMO.
GEOCHET
3
Философия дизайна не объективна. Не в списке. Тот факт, что большинству программистов что-то не нравится, не означает, что никто никогда не должен смотреть на это. Легко сделать глобальное использование глобалов без конца мира. Пусть он делает это, борется (зная, что он будет), и учится как.
user54650
7
Рич прав. Этот ответ ничего не говорит о том, что является / не является плохим (или о том, как глобальные переменные можно безопасно использовать), только о том, что «они не так плохи, как все это. Таким образом, он только преуменьшает проблемы.
Джальф
4
Я не согласен с тем, что глобальные переменные настолько «плохи, насколько вы их делаете». Я думаю, что одна из главных проблем, особенно в этом многопользовательском, взаимосвязанном мире, в котором большинство из нас живет, работает и программирует, заключается в том, что глобальные переменные дают кому-то, у кого еще, возможность сделать ваш код плохим.
gariepy
@gariepy, пока я не знаю, хотя речь идет о статике: D хорошо, вот и все ... и у моего приложения есть только одна или две глобальные переменные, одна из которых поставляется с Visual Studio, DEBUG и TRACE, которые мы обычно не используем: D
DeadManN
17

Я бы ответил на этот вопрос другим вопросом: пользуетесь ли вы сингелтонами / плохо ли сингелтон?

Потому что (почти все) использование сингелтона является прославленной глобальной переменной.

Гэвин Миллер
источник
11
Я собирался опубликовать умный комментарий, говорящий: «Они плохие, только если вы называете их глобальными, а не одиночными», но вы меня опередили.
SMO
Я все еще пытаюсь выяснить, что за чертовы одиночки LOL.
GeoffreyF67
1
@ Geoffrey: вот несколько хороших описаний SO - stackoverflow.com/questions/11831/… и для некоторых хороших ссылок: stackoverflow.com/questions/11831/…
Гэвин Миллер
10
Для записи, синглтон - это глобальная переменная с прославленным именем Design Patterns (tm) (lol), чтобы оно звучало законно. Это одинаково плохо по тем же причинам.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
@GavinMiller Говорят, что все в порядке, если вы используете простак ... оу, эвфемизм синглтона?
Хуан Мендес,
14

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

Несколько плюсов:

  • Можно получить доступ из любой функции.
  • Можно получить доступ из нескольких потоков.
  • Никогда не выйдет за рамки, пока программа не закончится.

Несколько минусов:

  • Доступ к ним возможен из любой функции, без необходимости явного перетаскивания в качестве параметра и / или документирования.
  • Не потокобезопасен.
  • Загрязняет глобальное пространство имен и потенциально вызывает конфликты имен, если не приняты меры для предотвращения этого.

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

Несколько потенциальных решений некоторых проблем:

  • Подумайте, действительно ли они являются лучшим или наиболее эффективным решением проблемы. Если есть какие-то лучшие решения, используйте это вместо.
  • Поместите их в пространство имен [C ++] или одноэлементную структуру [C, C ++] с уникальным именем (хорошим примером будет Globalsили GlobalVars), или используйте стандартное соглашение об именах для глобальных переменных (таких как global_[name]или g_module_varNameStyle(как упомянуто underscore_d в комментариях). )). Это будет как документировать их использование (вы можете найти код, который использует глобальные переменные, выполняя поиск по пространству имен / имени структуры), так и минимизировать влияние на глобальное пространство имен.
  • Для любой функции, которая обращается к глобальным переменным, явно задокументируйте, какие переменные она читает и какие пишет. Это облегчит поиск неисправностей.
  • Поместите их в собственный исходный файл и объявите их externв связанном заголовке, чтобы их использование могло быть ограничено модулями компиляции, которым необходим доступ к ним. Если ваш код основан на большом количестве глобальных переменных, но для каждого модуля компиляции требуется доступ только к нескольким из них, вы можете рассмотреть возможность сортировки их по нескольким исходным файлам, чтобы было проще ограничить доступ каждого файла к глобальным переменным.
  • Настройте механизм их блокировки и разблокировки и / или спроектируйте свой код таким образом, чтобы как можно меньшему количеству функций требовалось фактически изменять глобальные переменные. Чтение их намного безопаснее, чем их написание, хотя в многопоточных программах все еще могут возникать проблемы с потоками.
  • По сути, минимизируйте доступ к ним и максимизируйте уникальность имени. Вы хотите избежать коллизий имен и иметь как можно меньше функций, которые потенциально могут изменить любую переменную.

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

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


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

Джастин Тайм - Восстановить Монику
источник
1
+1 за прагматизм. Синглтон часто просто добавляет шаблон, чтобы превратить экземпляр и рефакторинг в члены, и вы получите ... глобальные переменные, просто маскирующиеся под другим именем. Зачем беспокоиться, кроме как избежать греха глобалов из-за простоты техники? Пространства имен хороши как барьер, но я нахожу простое g_module_varNameStyleсовершенно разборчивым. Чтобы быть ясным, я не использую глобальные переменные, если я могу легко избежать их - ключевое слово легко , потому что, поскольку я перестал верить, что их нужно избегать - или, скорее, запутать - любой ценой, я провожу намного лучше, и мои код (шок!) намного опрятнее
underscore_d
@underscore_d В основном это просто способ различать глобальные и локальные переменные, а также упростить поиск глобальных переменных при поиске в вашем коде, чтобы избежать путаницы в отношении того, является ли переменная глобальной или локальной / параметр / член / и т. д. Стандартное соглашение об именах, подобное вашему, работает так же хорошо, если оно согласовано. Редактирование моего ответа с использованием стандартной идеи именования, спасибо.
Джастин Тайм - Восстановить Монику
1
«Для любой функции ... явно задокументируйте, какие переменные» - помните, что это переходное отношение. Если функция A вызывает функции B и C, то она читает и записывает переменные, записанные обеими (плюс те, которые прямо в ее теле)
Caleth
11

Как кто-то сказал (я перефразирую) в другой теме: «Подобные правила не должны нарушаться, пока вы полностью не поймете последствия этого».

Бывают ситуации, когда необходимы глобальные переменные или, по крайней мере, они очень полезны (например, работа с системными обратными вызовами). С другой стороны, они также очень опасны по всем причинам, которые вам сказали.

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

Брайан Постов
источник
1
Я согласен, если вы понимаете последствия, это нормально, нарушайте правила, но если вы ловите себя на том, что часто делаете это, вы делаете что-то не так
Хуан Мендес,
9

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

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

Мишель
источник
9

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

gnovice
источник
ленивая метафора лишена контекста! = ответ
underscore_d
1
@underscore_d: я не согласен. Это вопрос для обсуждения, даже если он не помечен как таковой (вероятно, из-за его возраста), и поэтому ответы, подобные этому, совершенно верны, и он подчеркивает, что действительно отвечает на вопрос ОП.
gariepy
7

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

Леонидас
источник
7

Я думаю, что ваш профессор пытается избавиться от вредной привычки еще до того, как она начнется.

Глобальные переменные имеют свое место, и, как говорили многие люди, знание, где и когда их использовать, может быть сложным. Так что я думаю, а не вдаваться в подробности того, почему, как, когда и где глобальные переменные ваш профессор решил просто запретить. Кто знает, он может отменить их в будущем.

бом
источник
7

Точно нет. Хотя злоупотреблять ими ... это плохо.

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

jheriko
источник
3
-1 Существует множество причин для предостережения от глобальных переменных: для меня самая большая из них заключается в том, что скрытые зависимости и глобальные возможности делают тестирование кода любым предсказуемым способом чрезвычайно трудным. Если вы не цените возможность автоматического тестирования кода, я бы сказал, что глобальные переменные не причинят вам ничего, кроме боли. И кроме того, в хорошо структурированной программе всегда есть альтернативы.
JKP
1
Вы говорите, что это чрезмерная генерализация, осторожное использование глобального состояния не мешает автоматическому тестированию - фактически почти все приложения имеют глобальное состояние, независимо от того, упаковано ли оно в динамически размещенные экземпляры хорошо инкапсулированных объектов или статические данные, которые полностью раскрывают его. концептуально не имеет значения, есть еще зависимости - речь идет о том, как они кодируются.
jheriko
1
Именно. Они не столько "плохи", сколько "легко ломаются", в основном. Если вы знаете, как их использовать, не нарушая ничего, и когда использовать их вместо альтернативы, они могут быть полезны. В противном случае ... не так много.
Джастин Тайм - Восстановить Монику
4

Глобальные переменные хороши в небольших программах, но ужасны, если используются в больших программах тем же способом.

Это означает, что вы можете легко привыкнуть использовать их во время обучения. Это то, от чего ваш профессор пытается вас защитить.

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

Darron
источник
4

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

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

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

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

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

А пока просто делайте то, что говорит тот, кто говорит громче всего или несет самую большую палку (до тех пор, пока вы не будете кричать громко и нести самую большую палку).

Старожил
источник
4
Это просто еще один способ сказать: «Никто никогда не был уволен за покупку IBM»?
Гордон Поттер
1
Хорошая мысль, что для некоторых приложений использование глобальных переменных может на самом деле облегчить работу. В общем, использование глобальных переменных является источником проблем со скрытыми путями связи между разделами источника. Однако наличие области общей памяти, на которую ссылаются как на глобальную, используется для ряда реализаций, таких как интерфейсы устройства или, возможно, таблица глобальных параметров, содержащая различные виды констант, или таблица переходов.
Ричард Чемберс
4

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

Большую часть времени, когда вы выполняете многопоточность, вам нужно делиться чем-то. Например, в шаблоне «производитель-потребитель» вы можете использовать некоторую потокобезопасную очередь, содержащую рабочие блоки. И вам разрешено делиться этим, потому что эта структура данных является поточно-ориентированной. Является ли эта очередь глобальной или нет, совершенно не имеет значения, когда речь заходит о безопасности потоков.

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

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

Андреас Хефербург
источник
3

Да, потому что, если вы позволите некомпетентным программистам использовать их (читайте 90%, особенно ученых), вы получите более 600 глобальных переменных, разбросанных по более чем 20 файлам, и проект из 12 000 строк, где 80% функций отменяют, возвращают недействительные и работают полностью в глобальном состоянии.

Быстро становится невозможно понять, что происходит в любой момент, если вы не знаете весь проект.

wezzman
источник
2

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

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

Например:-

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

Муфаддал Кагда
источник
2

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

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

Мааз Рехман
источник
1

Рано или поздно вам нужно будет изменить способ установки этой переменной или то, что происходит при обращении к ней, или вам просто нужно найти место, где она была изменена.

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

Bloodboiler
источник
1

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

Использование глобального вместо передачи аргумента часто быстрее, но если вы пишете многопоточное приложение, что вы часто делаете в настоящее время, оно обычно работает не очень хорошо (вы можете использовать статику потоков, но тогда выигрыш в производительности сомнителен) ,

Эрик Олссон
источник
1

В веб-приложениях внутри предприятия можно использовать для хранения данных сессии / окна / потока / пользователя на сервере по причинам оптимизации и для защиты от потери работы, когда соединение нестабильно. Как уже упоминалось, условия гонки должны быть обработаны. Мы используем один экземпляр класса для этой информации, и он тщательно управляется.

xxyzzy
источник
1

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

alaboudi
источник
0

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

Вамси Паван Махеш
источник
-1

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

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

Подробнее об этом здесь, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code

kiriloff
источник
Для потомков: это отчасти правильно в лучшем случае. «Локальные переменные» в этом ответе относятся к локальным переменным потока , а не к более распространенным локальным переменным области видимости, на которые ссылается OP. Побочные эффекты от изменения глобальных переменных небезопасным способом очень отличаются от побочных эффектов от изменения глобального состояния не одновременно.
Жюль