グローバルは避けられません。
それは古い議論ですが、上記の回答でそれらを逃したので、私はまだいくつかの考えを追加したいと思います。これらの回答は、グローバルが多すぎることを単純化し、問題の解決策ではない解決策を提示します。問題は、グローバル変数とキーワードグローバルの使用を処理する適切な方法は何ですか?そのためには、まずグローバルとは何かを調べて説明する必要があります。
この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フレームワークを使用して、インターフェースの実装を変更したことがありますか?インターフェースは実際にはグローバルです。
グローバルに使用されているもう1つのアプリケーションは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 'は変更不可能なグローバルです。機能を機能させるために必要な機能の外側には大きな世界があります。
ゴードンの答えは正しくありません。なぜなら、彼は関数の独立性を過大評価し、関数を嘘つきと呼ぶことは状況を単純化しすぎているからです。関数は嘘をつかないので、彼の例を見てみると、関数は正しく設計されていません-彼の例はバグです。(ちなみに、コードを分離する必要があるという私はこの結論に同意します。)decezeの答えは、実際には状況の適切な定義ではありません。関数は常により広い範囲内で機能し、彼の例はあまりにも単純化しています。定数を返すので、その関数は完全に役に立たないということは、私たち全員が同意します。その機能はとにかく悪いデザインです。練習が悪いことを示したい場合は、適切な例を挙げてください。アプリケーション全体で変数の名前を変更することは、優れたIDE(またはツール)を使用することで大したことではありません。問題は変数のスコープについてであり、関数とスコープの違いではありません。関数がプロセスでその役割を実行するための適切な時間があります(そのため、最初に関数が作成されます)。その適切な時に、アプリケーション全体の機能に影響を与える可能性があり、グローバル変数にも作用します。xzyferの答えは、引数のないステートメントです。手続き型関数やOOP設計がある場合、グローバルはアプリケーションに存在します。グローバルの値を変更する次の2つの方法は基本的に同じです。したがって、グローバル変数にも取り組んでいます。xzyferの答えは、引数のないステートメントです。手続き型関数やOOP設計がある場合、グローバルはアプリケーションに存在します。グローバルの値を変更する次の2つの方法は基本的に同じです。したがって、グローバル変数にも取り組んでいます。xzyferの答えは、引数のないステートメントです。手続き型関数やOOP設計がある場合、グローバルはアプリケーションに存在します。グローバルの値を変更する次の2つの方法は基本的に同じです。
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
どちらの場合も、特定の関数内で$ zの値が変更されます。どちらのプログラミング方法でも、コードの他の多くの場所でこれらの変更を行うことができます。グローバルを使用すると、どこでも$ zを呼び出してそこで変更できると言えます。はい、できます。しかし、あなたはしますか?そして、不適切な場所で行われた場合、それはバグと呼ばれるべきではありませんか?
Bob Fangerがxzyferについてコメントしています。
だれでも、特に「グローバル」というキーワードだけを使用する必要がありますか?いいえ。ただし、他の種類のデザインと同様に、それが何に依存し、何に依存するかを分析してください。それがいつ変化し、どのように変化するかを調べてください。グローバル値の変更は、すべての要求/応答で変更できる変数でのみ発生する必要があります。つまり、プロセスの機能フローに属する変数のみであり、その技術的な実装には属していません。ログインページへのURLのリダイレクトは、技術的な実装へのインターフェイスに使用される実装クラスであるプロセスの機能フローに属します。後者はアプリケーションの異なるバージョンの間に変更できますが、すべての要求/応答でそれらを変更するべきではありません。
グローバルとキーワードグローバルの操作に問題がある場合とそうでない場合をさらに理解するために、ブログについて書くときにWim de Bieからの次の文を紹介します。「個人的はい、私的いいえ」。関数が自身の機能のためにグローバル変数の値を変更している場合、そのグローバル変数のプライベート使用とバグを呼び出します。しかし、ユーザーのログインページへのリダイレクトのように、アプリケーション全体の適切な処理のためにグローバル変数の変更が行われた場合、それは私の考えではおそらく良い設計であり、定義上悪いわけではなく、アンチパターン。
Gordon、deceze、xzyferの回答を振り返ってみると、例としてすべて 'private yes'(およびバグ)があります。それが彼らがグローバルの使用に反対している理由です。私もします。ただし、私がこの回答で何度か行ったような「個人的はい、個人的いいえ」の例は付いていません。