全球人是不可避免的。
这是一个古老的讨论,但是我仍然想补充一些想法,因为我在上述答案中想念它们。这些答案简化了整体问题,提供了根本无法解决问题的解决方案。问题是:处理全局变量和使用关键字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框架,您是否曾经更改过接口的实现?接口实际上是全局的。
另一个全球使用的应用程序是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是全局变量,includes / install.core.inc'是不可修改的全局变量。为了使该功能发挥作用,任何功能之外都存在广阔的世界。
戈登的答案是不正确的,因为他高估了函数的独立性,称函数为骗子会简化这种情况。函数不会说谎,当您查看他的示例时,该函数的设计不正确-他的示例是一个错误。(顺便说一句,我同意这样的结论,即应该使代码解耦。)降序的答案并不是对情况的正确定义。函数总是在更大的范围内起作用,他的例子太简单了。我们都会同意他的观点,即该函数完全无用,因为它返回一个常数。该功能无论如何都是不好的设计。如果您想证明这种做法不好,请举一个相关的例子。使用良好的IDE(或工具)在整个应用程序中重命名变量并不重要。问题是关于变量的范围,而不是与函数范围的差异。有一个适当的时间让一个函数在流程中执行其角色(这就是为什么首先创建它的原因),并且在那个适当的时间,它可能会影响整个应用程序的功能,因此也要处理全局变量。xzyfer的答案是没有论点的陈述。如果您具有程序功能或OOP设计,则全局变量与应用程序中的变量一样。接下来的两种更改全局值的方法基本相同:因此也可以处理全局变量。xzyfer的答案是没有论点的陈述。如果您具有程序功能或OOP设计,则全局变量与应用程序中的变量一样。接下来的两种更改全局值的方法基本相同:因此也可以处理全局变量。xzyfer的答案是没有论点的陈述。如果您具有程序功能或OOP设计,则全局变量与应用程序中的变量一样。接下来的两种更改全局值的方法基本相同:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
在这两种情况下,$ z的值都在特定函数内改变。可以通过两种编程方式在代码的其他许多地方进行这些更改。您可以说使用global可以在任何地方调用$ z并在那里进行更改。是的你可以。但是你会吗?当在不适当的地方进行操作时,不应该将其称为错误吗?
Bob Fanger在xzyfer上发表了评论。
那么,是否应该有人使用任何东西,尤其是关键字“ global”?不,但是就像任何类型的设计一样,请尝试分析它所依赖的内容以及所依赖的内容。尝试找出它何时更改以及如何更改。更改全局值仅应针对可随每个请求/响应更改的变量进行。也就是说,仅属于那些属于流程功能流程的变量,而不属于其技术实现。URL到登录页面的重定向属于流程的功能流,该实现类用于技术实现的接口。您可以在应用程序的不同版本中更改后者,但不应在每个请求/响应中都更改后者。
为了进一步了解使用globals和关键字global何时会出现问题,何时不使用,我将介绍下一个句子,该句子是Wim de Bie在撰写博客时写的:“个人是,私人否”。当一个函数由于其自身的功能而更改全局变量的值时,我将这种私有使用称为全局变量和错误。但是,如果要对全局变量进行更改以对整个应用程序进行适当处理,例如将用户重定向到登录页面,那么在我看来,这可能是好的设计,从定义上来说不是坏的,而且肯定不是反模式。
回顾戈登的答案,deceze和xzyfer:他们都以“ private yes”(和错误)为例。这就是为什么他们反对使用全局变量的原因。我也会的 但是,它们不带有“个人是,私人否”的示例,就像我在此答案中多次提到的那样。