글로벌은 피할 수 없습니다.
오래된 토론이지만 위에서 언급 한 답변에서 그리워서 몇 가지 생각을 추가하고 싶습니다. 이러한 대답은 글로벌이 너무 많은 것을 단순화하고 문제에 대한 해결책이 아닌 해결책을 제시합니다. 문제는 글로벌 변수와 글로벌 키워드를 사용하는 적절한 방법은 무엇입니까? 이를 위해 먼저 글로벌이 무엇인지 조사하고 설명해야합니다.
이 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 '는 수정할 수없는 전역입니다. 그 기능이 제 역할을하도록하기 위해 필요한 기능 외에는 큰 세계가 있습니다.
Gordon의 대답은 틀 렸습니다. 왜냐하면 그는 함수의 독립성을 과대 평가하고 함수를 거짓말 쟁이라고 부르는 것이 상황을 지나치게 단순화하기 때문입니다. 함수는 거짓말을하지 않으며 그의 예제를 살펴보면 함수가 부적절하게 설계되었습니다. 그의 예제는 버그입니다. (덧붙여서 저는 코드를 분리해야한다는 결론에 동의합니다.) 속임수에 대한 대답은 실제로 상황에 대한 적절한 정의가 아닙니다. 함수는 항상 더 넓은 범위 내에서 작동하며 그의 예는 너무 단순합니다. 우리는 그 함수가 상수를 반환하기 때문에 완전히 쓸모 없다는 데 동의 할 것입니다. 그 기능은 어쨌든 나쁜 디자인입니다. 관행이 나쁘다는 것을 보여주고 싶다면 관련 예를 들어주세요. 응용 프로그램 전체에서 변수의 이름을 바꾸는 것은 좋은 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에 대해 언급합니다.
그렇다면 누구나 무엇이든 특히 '글로벌'이라는 키워드를 사용해야합니까? 아니요,하지만 모든 유형의 디자인과 마찬가지로 무엇이 의존하고 무엇이 의존하는지 분석하려고 노력하십시오. 그것이 언제 바뀌고 어떻게 바뀌는 지 알아보십시오. 전역 값 변경은 모든 요청 / 응답으로 변경 될 수있는 변수에서만 발생해야합니다. 즉, 기술 구현이 아니라 프로세스의 기능 흐름에 속하는 변수에만 해당됩니다. URL을 로그인 페이지로 리디렉션하는 것은 기술 구현에 대한 인터페이스에 사용되는 구현 클래스 인 프로세스의 기능 흐름에 속합니다. 애플리케이션의 다른 버전에서 후자를 변경할 수 있지만 모든 요청 / 응답에서 변경해서는 안됩니다.
globals 및 키워드 global로 작업하는 데 문제가있는 경우를 더 이해하기 위해 블로그에 대해 쓸 때 Wim de Bie에서 제공하는 다음 문장을 소개하겠습니다. 'Personal yes, private no'. 함수가 자체 기능을 위해 전역 변수의 값을 변경할 때 전역 변수와 버그의 사적인 사용을 호출 할 것입니다. 그러나 사용자를 로그인 페이지로 리디렉션하는 것과 같이 응용 프로그램 전체를 적절하게 처리하기 위해 전역 변수를 변경하면 정의상 나쁘지 않고 확실히 좋은 디자인이 아니라고 생각합니다. 안티 패턴.
Gordon, deceze 및 xzyfer의 답변을 되돌아 보면 모두 'private yes'(및 버그)를 예로 들어 있습니다. 그것이 그들이 글로벌 사용에 반대하는 이유입니다. 나도 할 것입니다. 그러나 그들은 '개인적 예, 비공개 아니오'와 함께 제공되지 않습니다.이 답변에서 여러 번했던 것과 같은 예입니다.