Глобалы неизбежны.
Это старое обсуждение, но я все же хотел бы добавить некоторые мысли, потому что мне их не хватает в вышеупомянутых ответах. Эти ответы упрощают то, что такое глобальное, и представляют решения, которые вовсе не являются решениями проблемы. Проблема в том, как правильно работать с глобальной переменной и использовать ключевое слово 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 - утверждение без аргументов. Глобальные объекты также присутствуют в приложении, если у вас есть процедурные функции или дизайн ООП. Следующие два способа изменить значение глобального по существу одинаковы: следовательно, мы также работаем с глобальными переменными. Ответ xzyfer - утверждение без аргументов. Глобальные объекты также присутствуют в приложении, если у вас есть процедурные функции или дизайн ООП. Следующие два способа изменить значение глобального по существу одинаковы: следовательно, мы также работаем с глобальными переменными. Ответ xzyfer - утверждение без аргументов. Глобальные объекты также присутствуют в приложении, если у вас есть процедурные функции или дизайн ООП. Следующие два способа изменить значение глобального по существу одинаковы:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
В обоих случаях значение $ z изменяется в рамках определенной функции. При обоих способах программирования вы можете вносить эти изменения в кучу других мест кода. Можно сказать, что с помощью global вы можете вызвать $ z где угодно и изменить там. Да, ты можешь. Но ты будешь? И если это сделано в неподходящих местах, не следует ли тогда называть это ошибкой?
Боб Фангер комментирует xzyfer.
Должен ли кто-нибудь тогда просто использовать что-нибудь, особенно ключевое слово «глобальный»? Нет, но, как и любой другой дизайн, постарайтесь проанализировать, от чего он зависит, а что от него. Постарайтесь узнать, когда оно меняется и как меняется. Изменение глобальных значений должно происходить только с теми переменными, которые могут изменяться при каждом запросе / ответе. То есть только к тем переменным, которые относятся к функциональному потоку процесса, а не к его технической реализации. Перенаправление URL-адреса на страницу входа принадлежит функциональному потоку процесса, классу реализации, используемому для интерфейса к технической реализации. Вы можете изменить последнее в разных версиях приложения, но не должны изменять их при каждом запросе / ответе.
Чтобы лучше понять, когда возникает проблема при работе с глобальными объектами и ключевым словом global, а когда нет, я представлю следующее предложение, которое исходит от Вима де Би, когда он пишет о блогах: «Личное да, личное нет». Когда функция изменяет значение глобальной переменной ради собственного функционирования, я буду называть это частное использование глобальной переменной и ошибкой. Но когда изменение глобальной переменной выполняется для правильной обработки приложения в целом, например, перенаправление пользователя на страницу входа в систему, то, на мой взгляд, возможно, хороший дизайн, а не по определению плохой и, конечно, не антипаттерн.
Оглядываясь назад на ответы Gordon, deceze и xzyfer: у всех них в качестве примеров есть «личное да» (и ошибки). Вот почему они против использования глобальных переменных. Я бы тоже. Однако в них нет примеров типа «личное да, частное нет», как я уже несколько раз делал в этом ответе.