Почему глобальные переменные-это зло?



Я пытался найти хороший источник, который объясняет, почему использование global считается плохой практикой в python (и в программировании в целом). Может кто-нибудь указать мне на один или объяснить здесь?

696   4  

4 ответов:

Это не имеет ничего общего с Python; глобальные переменные-это плохо в любом языке программирования.

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

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

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

но, конечно, ваш вопрос имеет много ответов, поэтому лучше всего просто google "почему глобальные переменные плохие". Некоторые примеры:

Если вы хотите пойти глубже и узнать, почему побочные эффекты все о, и многие другие поучительные вещи, вы должны узнать функциональные Программирование:

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

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

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

cache = {}

def foo(args):
    global cache

    cache[args] = ...

это упрощает отслеживание манипуляций глобалов.

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

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

(вероятно) нарушение определения чистой функции

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

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

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

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

(вероятно) нарушение принципа модульного тестирования F. I. R. S. T

далее, Если вы рассматриваете модульное тестирование и принцип F. I. R. S. T (Fтесты АСТ ятесты ndependent, Repeatable, Sэльф-проверка и Tсвоевременные), вероятно, нарушает принцип независимого тестирования (что означает, что испытания не зависят друг от друга).

наличие глобальной переменной (не всегда), но в большинстве случаев (по крайней мере, из того, что я видел до сих пор) заключается в подготовке и передаче результатов другим функциям. Это также нарушает этот принцип. Если глобальная переменная была использована таким образом (т. е. глобальная переменная, используемая в функции X, должна быть сначала установлена в функции Y), это означает, что для модульного теста функция X сначала вы должны запустить функцию test/run Y.

глобальные переменные как константы

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

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

Они необходимы, экран является хорошим примером. Однако в многопоточной среде или при участии многих разработчиков на практике часто возникает вопрос: кто (ошибочно) установил или очистил его? В зависимости от архитектуры, анализ может быть дорогостоящим и часто требуется. При чтении глобального var может быть в порядке, запись в него должна контролироваться, например, одним потоком или потокобезопасным классом. Следовательно, глобальные vars возникают страх перед высокими затратами на разработку, возможными последствия, за которые сами себя считают злом. Поэтому в целом, это хорошая практика, чтобы сохранить количество низкая Варс.

Comments

    Ничего не найдено.