Почему глобальные переменные плохи в однопоточном встраиваемом приложении без ОС

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

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

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

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


person loneRanger    schedule 16.05.2009    source источник


Ответы (13)


Это не так.

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

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

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

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

person Will Hartung    schedule 16.05.2009
comment
Я ценю множество комментариев и ответов. Я выбрал это в качестве своего ответа, потому что он наиболее четко резюмирует мое обоснование. Я действительно чувствую себя «забавным», выбирая ответ, подтверждающий мой выбор дизайна, но, эй, думаю, я все равно буду. - person loneRanger; 20.05.2009
comment
Это один из лучших ответов, которые я когда-либо читал на этом сайте. - person Ellis; 30.07.2015

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

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

  1. They violate good object-oriented design
  2. They make your code difficult to unit-test, since you can not test individual blocks of code without setting up all of the global variables that the code expects to see
  3. They increase coupling in your code: actions in one block of code may affect things in another block of code in unpredictable ways via a shared global variable

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

  1. They make it easy to share a single resource between many functions
  2. They can make code easier to read

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

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

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

person e.James    schedule 16.05.2009
comment
Согласованный. Как и многие правила в программном обеспечении (особенно C), бывают случаи, когда ситуация требует, чтобы они были нарушены или нарушены. Я стараюсь по возможности избегать глобальных переменных, но есть небольшое количество случаев, когда они являются лучшим решением проблемы. - person Steve Melnikoff; 17.05.2009
comment
глобальные переменные также могут затруднить чтение кода ... и IMO, что более вероятно. - person smerlin; 18.07.2010

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

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

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

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

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

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

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

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

person TStamper    schedule 16.05.2009
comment
Глобальные значения могут быть видны только модулям, которые включают модуль, в котором они определены. Следуя этой логике, можно запретить публичные и защищенные поля, потому что каждый может получить к ним доступ путем наследования. - person Marco van de Voort; 18.05.2009

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

person Otávio Décio    schedule 16.05.2009
comment
Это то, о чем я хотел сказать. То, что сейчас он маленький и однопоточный, не означает, что так будет всегда. - person rampion; 16.05.2009
comment
rampion: отсутствует точка, которая является развязкой для повторного использования, а не для обеспечения безопасности потоков. - person ; 16.05.2009

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

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

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

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

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

person kgiannakakis    schedule 18.05.2009
comment
Отличное дополнение к основному ответу! - person ForeverLearning; 23.08.2018

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

person Community    schedule 19.07.2009

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

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

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

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

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

person John Christman    schedule 16.05.2009

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

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

person Charlie Martin    schedule 16.05.2009

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

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

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

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

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

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

person jalf    schedule 16.05.2009

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

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

Короче говоря, это становится кошмаром для обслуживания и отладки.

person rein    schedule 16.05.2009
comment
Почему это не так с указателями? Если у меня есть переменная, переданная указателем на другую функцию, не всегда легко увидеть, где было изменено ее значение. - person Nathan Fellman; 16.05.2009

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

person Richard    schedule 16.05.2009

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

person jholl    schedule 16.05.2009

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

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

Конечно, вы можете решить использовать глобальные переменные сейчас, и когда проект станет более сложным, вернитесь и переписайте его части, но зачем заставлять себя выполнять эту дополнительную работу? Вы с большей вероятностью (если вы вообще помните глобальные переменные) решите, что выполнение этой работы требует слишком больших усилий, и отпустите дизайн: в этот момент у вас проблемы!

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

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

person Casey    schedule 16.05.2009