Почему плохие глобальные переменные в однопоточном встроенном приложении - PullRequest
29 голосов
/ 16 мая 2009

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

Но у вас есть какие-то возражения в небольшом однопоточном корпусе без ОС? В моем случае я пишу свою встроенную систему на «С», если это имеет значение. Я также единственный разработчик продукта.

Почему устранение глобальных переменных сделает мой код лучше?

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

Ответы [ 13 ]

48 голосов
/ 16 мая 2009

Не будет.

Две фундаментальные проблемы с глобальными переменными - это просто загромождение пространства имен и тот факт, что «никто» не «контролирует» их (таким образом, потенциальные коллизии и конфликты с несколькими потоками).

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

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

Так что, не беспокойся об этом.

18 голосов
/ 16 мая 2009

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

Некоторые аргументы против глобальных переменных:

  1. Они нарушают хороший объектно-ориентированный дизайн
  2. Они затрудняют юнит-тестирование вашего кода, поскольку вы не можете тестировать отдельные блоки кода без установки всех глобальных переменных, которые код ожидает увидеть
  3. Они увеличивают связывание в вашем коде: действия в одном блоке кода могут непредсказуемым образом повлиять на вещи в другом блоке кода через общую глобальную переменную

Некоторые аргументы для глобальных переменных:

  1. Они упрощают совместное использование одного ресурса многими функциями.
  2. Они могут облегчить чтение кода

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

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

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

18 голосов
/ 16 мая 2009

Вот хорошая статья, объясняющая причину Почему глобальные переменные плохие

Почему следует избегать глобальных переменных, когда они не нужны?

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

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

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

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

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

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

8 голосов
/ 16 мая 2009

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

7 голосов
/ 18 мая 2009

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

  • Различают статические и глобальные переменные. Статические переменные могут использоваться из всех функций в одном и том же C-файле. Они являются эквивалентом закрытых членов в классе C ++. В Си вы должны выполнять работу компилятора самостоятельно. Используйте ключевое слово static, чтобы избежать случайного использования переменной за пределами модуля и сделать ее видимой. Возможно, вы захотите добавить префикс к имени модуля.

  • Следуйте соглашению об именах глобальных переменных (используется многими C-файлами). Сделайте ясно, что они глобальны.

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

  • При необходимости используйте ключевое слово volatile. Это необходимо, если глобальная переменная изменена ISR.

5 голосов
/ 20 июля 2009

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

2 голосов
/ 16 мая 2009

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

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

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

Если вы решили использовать глобальную переменную, постарайтесь комментировать их и давать им хорошие имена. Меня действительно беспокоит, когда люди создают глобальные переменные, такие как "bool bIsFound;"

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

1 голос
/ 16 мая 2009

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

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

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

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

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

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

1 голос
/ 16 мая 2009

Короткий ответ: глобальные переменные исторически были источником тонких ошибок. Но затем (надевая мою функциональную шапку программиста) все переменные были источниками тонких ошибок.

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

0 голосов
/ 16 мая 2009

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

...