全球化是不可避免的。
这是一个古老的讨论,但我仍然想补充一些想法,因为我怀念他们在上面提到的答案。这些答案简化了什么是全球性的太多,并提出了根本不是解决问题的解决方案。问题是:处理全局变量和使用关键字全局的正确方法是什么?要做到这一点,我们首先要研究和描述什么是全局的。
看看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',
);
这里有很多不可见的依赖项。这些常量实际上是类。您还可以在此框架的某些页面中看到Required_Onone。SEVENT_ONE是一个全局依赖项,因此会创建外部依赖项。对于一个框架来说,这是不可避免的。如果没有大量依赖的外部代码,如何创建像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是全局的,include/install.core.inc‘是不可修改的全局的。为了让这个功能完成它的工作,除了任何函数之外,还有一个很大的世界。
戈登的回答是不正确的,因为他高估了一个函数的独立性,而称一个函数为骗子是过分简化了情况。函数不会说谎,当您查看他的示例时,该函数的设计是不正确的-他的示例是一个bug。(顺便说一句,我同意这样的结论,即应该将代码解耦。)欺骗的答案并不是对情况的正确定义。函数总是在更大的范围内工作,他的例子太简单了。我们都会同意他的观点,即函数是完全无用的,因为它返回一个常数。不管怎么说,这种功能的设计都很糟糕。如果你想证明实践是不好的,请提供一个相关的例子。在整个应用程序中重命名变量并不是什么大不了的,有一个好的IDE(或一个工具)。问题是变量的作用域,而不是函数作用域的不同。一个函数在过程中发挥作用是有适当时间的(这就是为什么首先创建它的原因),在适当的时候,它可能会影响整个应用程序的功能,因此也会处理全局变量。xzyfer的回答是一种没有论证的陈述。如果您有过程功能或OOP设计,则全局在应用程序中同样存在。接下来两种改变全局值的方法本质上是相同的:
function xzy($var){
global $z;
$z = $var;}function setZ($var){
$this->z = $var;}
在这两种情况下,$z的值都是在特定函数中更改的。在这两种编程方式中,您都可以在代码中的其他地方进行这些更改。您可以说,使用全局,您可以调用$z在任何地方,并在那里改变。可以,停那儿吧。但你会吗?当它在不合适的地方做的时候,它不应该被称为虫子吗?
鲍勃·范格对Xzyfer的评论。
那么,应该有人使用任何东西,尤其是关键字“全局”吗?不,但就像任何类型的设计一样,试着分析它所依赖的和依赖于它的东西。试着找出它什么时候变化,以及它是如何变化的。更改全局值应该只对那些可能随每个请求/响应而变化的变量发生。也就是说,只适用于属于流程功能流的变量,而不属于其技术实现。将URL重定向到登录页面属于流程的功能流,流程是用于技术实现接口的实现类。您可以在应用程序的不同版本中更改后者,但不应更改每个请求/响应的版本。
为了进一步了解在处理全局词和关键字全局时遇到的问题,以及什么时候不是,我将介绍下一句,它来自Wim de Bie在写博客时说的话:‘个人是的,私人的不是’。当一个函数为了其自身的功能而改变全局变量的值时,我将称之为全局变量和bug的私有使用。但是,当全局变量的改变是为了对整个应用程序进行适当的处理时,比如用户重定向到登录页面,那么在我看来,在我看来可能是一个好的设计,从定义上来说不是不好的,当然也不是反模式。
回顾戈登、欺骗和xzyfer的答案:他们都有“私人的是”(和bug)作为例子。这就是为什么他们反对使用全球化。我也会这么做的。然而,他们并没有附带“个人是的,私人的不”-就像我在这个答案中做过几次这样的例子。