2011-01-05 4 views
2

私は、Factoryクラスを使ってオブジェクトのインスタンス化を管理し、コンストラクタに任意の依存オブジェクト(Dependency Injection)を渡しています。PHP OOP ::すべてのクラスにアクセス可能なグローバル設定値を保持する

function createBasket() { 
    //pass in dependent objects 
    $apiCon = $this->createAPIConnector($this); 
    $basket = new Basket($this, $apiCon); 
    return $basket; 
} 

私は、よりシンプルで堅牢なユニットテストを可能にするために、(工場以外)の任意のクラス内の「新しい」キーワードを使用しないようにしようとしています、明確なコードなど

さて、私の質問はに関し、多くのクラスが必要とする設定値

$apiURL = 'http://some.api.com'; 
$apiKey = 'abcde12345'; 
$adminEmail = '[email protected]'; 

これらの値は、アプリケーションインスタンスごとに一定です。私は現在、シングルトンクラスConfigでそれらを持っていると、彼らは従うことによって、任意のクラス内から到達可能である:

$cfg = Config::getInstance(); 
$address = $cfg->apiURL; 

しかし、このクラスのインスタンスはまだそれを呼び出す任意のクラス内の依存関係ですので、私は合格を考える必要がありますこれをクラスコンストラクタに

function createBasket() { 
    //pass in dependent objects 
    $apiCon = $this->createAPIConnector($this); 
    $cfg = Config::getInstance(); 
    //pass singleton config object to constructor 
    $basket = new Basket($this, $apiCon, $cfg); 
    return $basket; 
} 

...または多分むしろ、コンストラクタ経由よりも、setメソッドを経由して、それらを渡す:

function createBasket() { 
    //pass in dependent objects 
    $apiCon = $this->createAPIConnector($this); 
    $basket = new Basket($this, $apiCon); 
    //pass singleton config object to setter 
    $basket.setConfig(Config::getInstance()); 
    return $basket; 
} 

最良の方法上の任意のガイダンスははるかに高く評価されるだろう。

ありがとう、ジェームズ

+1

* [symfonyコンポーネント依存性注入コンテナ](http://components.symfony-project.org/dependency-injection) – Gordon

+0

依存性注入は行く方法 – DrDol

答えて

1

これは、グローバルに利用可能なシングルトン設定オブジェクトを持つという目的を破るようです。全体のポイントは、あなたが作るすべてのクラスへのパラメータとしてそれを渡す必要を避けることです。

+0

私は各クラスが単体テストできることを保証しようとしています。私はおそらくむしろSingletonクラスを削除するでしょう。なぜなら、それは実際にはvarsのグローバルな所有者として機能しているからです。私のアプリケーションでDependence Injectionを保持するためには、これらの「グローバルな」変数(およびヘルパー関数)がそれらを必要とするクラスに渡されるようにする方法が必要です。グローバルな空間にそれらを残したいのは魅力的ですが、6ヵ月後には世界的に大変なことを残念に思って、単体テストをもっと厄介なものにすることは間違いありません。 –

+0

答えがあります。シングルトンに依存しないようにコードをリファクタリングし、必要に応じてコンストラクタにヴァールを渡します。単体テストがより簡単になり、コードを簡単にフォローできます。 –

1

私はいつも定数として作った。私はこれが "最高の"解決策であるかどうかはわかりませんが、これを見て何度も使用しました。そのconst(静的なvarsの場合も同じですが、私はなぜ他のものより優れているのか聞くことに興味があります)は、あなたがニッキーになりたいならばおそらくオーバーヘッドを減らすクラスをインスタンス化する必要はありません...あなたは、単一のアレイまたはファイル内のすべてを設定し、それを定義し、ファイルを必要とし、それを使用して、私は同様の方法を使用し

SomeClass::MYCONST //to get your config info 
+0

私は同様の方法を使用しますが、 AndroidのContactsContract(http://developer.android.com/reference/android/provider/ContactsContract.html)に似たクラス – Don

+0

ありがとうございます。私の心配は、私のクラスに「隠れた」依存関係を持たないことともっと関係していると思います。これらの値をコンストラクタに明示的に渡すというアイデアは、特にアプリケーションを開発する新しい人にとって、はるかに明確なコードのIMOを作成します。オブジェクトが私たちに依存するものはすべて、コンストラクターargsでクリスタルクリアに見えます。おそらく、私はこれらのシンプルなグローバル変数については不必要に心配しています。オブジェクトや大規模/複雑なデータ構造はありません。このようなものを保持するだけのクラスを作成することは、OOPデザインの恩恵を受けることはありません...hmmm –

0

ような何かをする必要がある場合で、その後

class SomeClass 
{ 
    const MYCONS = "APIKEY or Whateva"; 
} 

それに応じて:

$config = array(
    'MYCONST_1'=>'myValue', 
    'USER'=>'username', 
    'PASSWORD'=>'y3ahr1ght' 
); 

foreach($config as $const=>$value){ 
    define($const,$value); 
} 
+0

私の場合、私はあなたのコード例に丁寧に同意しません。実行時に異なる値を持つ可能性のある変数にアプリケーションワイド定数を使用すると、テストするのがより難しくなります.1つのテストクラスに含まれるクラスごとに1つのテストスイートがある場合、スイート内の定数を変更できないため、ファイル用の2つのテストスイート。言い換えれば、私が何かを忘れていない限り、あなたの定数がどこでもアプリケーション全体で使用され、実行時にグローバルスコープで複数の値を持つことができれば、それは私の(謙虚な)意見では正しく感じられません。 – stefgosselin

関連する問題