2009-05-03 8 views
2

ある種の依存関係注入を使用している場合、私が理解しているように、別のオブジェクトとの構成関係(「has-a」関係)を持つオブジェクトを単体テストすると、実際には合成オブジェクトをモックすることができます。したがって、以下のコードは、一種ユニットテストは非常に困難にし、従って悪いと見なされるかもしれない:依存性注入のないオブジェクトの構成は悪いですか?

<?php 
class aSampleClass { 
    private $dependency; 
    public function __construct() { 
     $this->dependency = new otherClass; 
    } 
} 

このおもちゃの例は容易にパラメータとしてotherClassオブジェクトのインスタンスを渡すことによって、依存性注入を使用して変換されますコンストラクタに渡しますが、必ずしもそうではありません。上記のフォームのオブジェクト構成(「new」演算子がクラス実装で直接使用される)が悪いのですか?あなたは常にそのクラスを書くようにして、そのクラスの関連性を完全にテストできるようにする必要がありますか?

日付や金銭オブジェクトなどの単純なバリューオブジェクト(ドメイン駆動設計の言い回し)を使用している場合、依存性注入を使用すると、私のためにうまく動作しているようです。そのような場合は、問題のValueオブジェクトを直接インスタンス化するのが理にかなっているようです。例えば:

<?php 
    class anotherSampleClass { 
     public function getTimeDifferencePhrase() { 
      $now = new date_Time; 
      $then = new date_Time(time()-60*60*24); 
      return $now->relativeTimePhrase($then); 
     } 
    } 

は確かに、この例では、それはまた、かなりモックオブジェクトやテストダブルを使用しようとしてよりdate_Timeオブジェクトの実装を行使するanotherSampleClassのユニットテストのためのより多くの意味があります。

思考?

答えて

0

これらのシナリオでは、明確なルールはありません。依存性注入は通常は良いことですが、必ずしも必要ではありません。それはあなたのクラスを分析し、誰が本当に依存関係を作成する責任を持っているかを理解することです。

意味的にクラスに属し、クラスが完全に責任を負う非常に単純なオブジェクトを扱っている場合、依存関係注入はオーバーエンジニアリングの可能性があります。あなたは実際にdate_Timeをテストする必要はないので、私はその特定の依存関係を注入することはありません。

もう1つ考慮すべきことは、その依存関係をコンストラクタ内に構築すると、クラスをテストできないものにするかどうかです。たとえば、乱数ジェネレータを使用するクラスで発生します。その場合、依存関係注入を使用しない場合、テストに適した数の予測可能なセットを与えるジェネレータを注入する方法はありません。

したがって、短い答え:通常は良いことですが、決して必ずしも必要ではありません。

0

このようなことは難しいことではありません。いくつかの純粋主義者はあなたが依存を注入すべきだと言う一方で、他の純粋主義者はもっと実用的なアプローチをとると言います。 VO自体には依存関係がないので、私はおそらくKISSの原則を呼び出すでしょうし、オブジェクト内に「新しくする」ことはまったく問題だと言います。これは特に、VOが同じモジュールに(DDDの言葉で)存在することになります。さらに、オブジェクト内のVOをインスタンス化しても、それをあまりテストすることはできません。

1

これはに依存しています。テストしています。 Dependency Injectionは、外部サービス(テストデータを持たない、単体テストに適さない)に依存することを心配することなく、クラスをテストするという問題を解決します。

値オブジェクト(または文字列、intなど)をモックしてクラスが正しく構築されたことをテストし、difference演算子を呼び出すことはありません。これは実装のすべての部分であり、それをテストすることに関連しています。

getRelativeTimeDifferencePhraseは、60 * 60 * 24 secondsが渡されたときに「24時間前」に正しく返されることをテストします。

ハードコードコーディングtime()は、コードが実行されたときに返すものが十分な精度で予測できないため、壊れやすいテストにつながることに気がつきます。time()これによりRealTimeServiceにつながり、制御可能なシームが導入されます。あなたはハードあなたは、あなたのコンストラクタにITimeServiceを渡すことになりますので、それは、何であるかtime()コーディングできるように - あなたのクラスがRealTimeServiceがあなたのMockTimeServiceを注入する方法を残さないだろうインスタンス持つ

。今、依存性注入があります。 ;)

1

依存性注入は実際に多くの問題を解決します。しかし、多くの人々はそれがコンポジションではなく集約であることに気付かない。 をインスタンス化する例では、他のクラスがあります。したがって、依存性注入を導入することで、実際にはCompositionとDemeterの法則の両方が破られ、集約が導入されます。

私はアーキテクチャを壊さない限り、依存性注入は素晴らしいと思います。多くの人々は、コンストラクタでの新しい演算子の使用は悪いと言う代わりに、インスタンスをコンストラクタに渡す必要がありますが、間違っています。ドメインに依存する必要があります。特にガベージコレクションのない言語では、混乱の原因になることもあります。たとえば、C++の経験則は、作成者がオブジェクトを破棄することです。だから、バッテリーを持っている電話が破壊されたら、誰がそのバッテリーを破壊するのだろうか?電話またはそれに渡されたオブジェクトはどれですか?しかし、いくつかの状況では、バッテリーを電話機に通したいと思うでしょう。たとえば、ファクトリをモデリングする場合などです。

あなたの質問には、「依存性注入のないオブジェクトの構成は悪いのですか?それはモデリングしているドメインに依存しますが、テスト容易性に対する設計を犠牲にすることはIMOにとっては悪いことです。あなたが不確かなものを見つけたら、あなたのデザインが正しいかどうかを見てください。私は通常、依存性注入を導入できるかどうかを確認します。問題が解決しない場合は、ファクトリメソッドを導入できるかどうかを確認します。そうでなければ、私は何か他のことをすることができるかどうかを見るでしょう。