Глобалы неизбежны.
Это старая дискуссия, но я все же хотел бы добавить некоторые мысли, потому что я скучаю по ним в вышеупомянутых ответах. Эти ответы упрощают то, что глобальное слишком много, и представляют решения, которые вовсе не являются решением проблемы. Проблема заключается в следующем: как правильно обращаться с глобальной переменной и использовать ключевое слово global? Для этого сначала нужно изучить и описать, что такое глобальный.
Посмотрите на этот код Zend - и, пожалуйста, поймите, что я не предполагаю, что Zend написан плохо:
class DecoratorPluginManager extends AbstractPluginManager
{
/**
* Default set of decorators
*
* @var array
*/
protected $invokableClasses = array(
'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
);
Здесь много невидимых зависимостей. Эти константы на самом деле являются классами.
Вы также можете увидеть require_once на некоторых страницах этого фреймворка. Require_once является глобальной зависимостью, следовательно, создает внешние зависимости. Это неизбежно для рамок. Как создать класс наподобие DecoratorPluginManager без большого количества внешнего кода, от которого он зависит? Он не может функционировать без множества дополнений. Используя Zend Framework, вы когда-нибудь меняли реализацию интерфейса? Интерфейс на самом деле является глобальным.
Еще одно глобально используемое приложение - Drupal. Они очень заботятся о правильном дизайне, но, как и любая большая платформа, у них много внешних зависимостей. Посмотрите на глобалы на этой странице:
/**
* @file
* Initiates a browser-based installation of Drupal.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
/**
* Global flag to indicate that site is in installation mode.
*/
define('MAINTENANCE_MODE', 'install');
// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the <a href="http://drupal.org/requirements">system requirements</a> page for more information.';
exit;
}
// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();
Когда-нибудь писал перенаправление на страницу входа? Это меняет глобальное значение. (И затем вы не говорите «WTF», что я считаю хорошей реакцией на плохую документацию вашего приложения.) Проблема с глобальными именами заключается не в том, что они являются глобальными, вам нужны они для того, чтобы иметь содержательное приложение. Проблема заключается в сложности всего приложения, которое может сделать его кошмаром.
Сеансы являются глобальными, $ _POST - глобальным, DRUPAL_ROOT - глобальным, include / install.core.inc 'является неизменяемым глобальным. За пределами любой функции существует большой мир, необходимый для того, чтобы эта функция выполняла свою работу.
Ответ Гордона неверен, потому что он переоценивает независимость функции, а вызов функции лжецом упрощает ситуацию. Функции не лгут, и когда вы смотрите на его пример, функция спроектирована неправильно - его пример - ошибка. (Кстати, я согласен с этим выводом, что нужно отделить код.)
Ответ децезе не совсем правильное определение ситуации. Функции всегда функционируют в более широкой области, и его пример слишком упрощен. Мы все согласимся с ним, что эта функция совершенно бесполезна, потому что она возвращает константу. Эта функция в любом случае плохой дизайн. Если вы хотите показать, что практика плохая, приведите соответствующий пример. Переименование переменных в приложении - это не проблема, если у вас есть хорошая IDE (или инструмент). Вопрос заключается в области действия переменной, а не в разнице области действия функции. У функции есть подходящее время для выполнения своей роли в процессе (именно поэтому она создается в первую очередь), и в это время она может влиять на функционирование приложения в целом, следовательно, также работать с глобальными переменными. ,
Ответом xzyfer является утверждение без аргументации. Глобальные переменные также присутствуют в приложении, если у вас есть процедурные функции или дизайн ООП. Следующие два способа изменения значения глобала по сути одинаковы:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
В обоих случаях значение $ z изменяется в конкретной функции. В обоих случаях программирования вы можете внести эти изменения в кучу других мест в коде. Вы можете сказать, что используя global, вы можете вызывать $ z где угодно и менять там. Да, ты можешь. А ты? И когда это сделано в неподходящих местах, разве это не должно быть названо ошибкой?
Боб Фэнджер комментирует xzyfer.
Должен ли кто-нибудь тогда просто что-нибудь использовать, особенно ключевое слово "global"? Нет, но, как и любой тип дизайна, попробуйте проанализировать, что зависит и что от него зависит. Попытайтесь выяснить, когда это изменяется и как это изменяется. Изменение глобальных значений должно происходить только с теми переменными, которые могут меняться при каждом запросе / ответе. То есть только к тем переменным, которые относятся к функциональному потоку процесса, а не к его технической реализации. Перенаправление URL на страницу входа в систему относится к функциональному потоку процесса, классу реализации, используемому для интерфейса с технической реализацией. Вы можете изменить последнее в разных версиях приложения, но не следует менять их при каждом запросе / ответе.
Чтобы лучше понять, когда возникает проблема работы с глобальными и ключевым словом global, а когда нет, я введу следующее предложение, которое приходит от Wim de Bie, когда пишет о блогах:
«Личное да, личное нет». Когда функция изменяет значение глобальной переменной ради своего собственного функционирования, я назову это частным использованием глобальной переменной и ошибкой. Но когда изменение глобальной переменной сделано для правильной обработки приложения в целом, например, перенаправления пользователя на страницу входа в систему, то это, по моему мнению, возможно хороший дизайн, не по определению плохой и, конечно, не анти-модель.
В ретроспективе к ответам Гордона, Десезе и Хзифера: у них у всех есть «личное да» (и ошибки) в качестве примеров. Вот почему они против использования глобалов. Я бы тоже так сделал. Они, однако, не содержат «личное да, личное нет» - примеры, которые я несколько раз приводил в этом ответе.