2009-07-13 13 views
12

単一の責任原則:クラス内のすべてのパブリックメソッドはすべてのクラス依存関係を使用する必要がありますか?

次のようなクラスがあるとします。

internal class SomeClass 
{ 
    IDependency _someDependency; 

    ... 


    internal string SomeFunctionality_MakesUseofIDependency() 
    { 
    ... 
    } 
} 

そして、関連する機能を追加したいのですが、はその目的を達成するために別の依存関係を使用します。おそらく、次のようなものです:

internal class SomeClass 
{ 
    IDependency _someDependency; 

    IDependency2 _someDependency2; 

    ... 


    internal string SomeFunctionality_MakesUseofIDependency() 
    { 
    ... 
    } 

    internal string OtherFunctionality_MakesUseOfIDependency2() 
    { 
    ... 
    } 
} 

この新しい機能の単体テストを書く(または既存の機能に対して持っている単体テストを更新する)と、自分自身がSomeClass(SUT)私がテストしようとしている機能の特定のビットのために必要でない依存関係のためにヌルを渡している間。

これは私にとって悪い匂いのようですが、私がこの道を歩いている理由は、私が導入した新しい機能のそれぞれについて新しいクラスを作成することができたからです。これは悪いもののように思えたので、同様の機能をまとめてグループ化しようとしました。

私の質問:クラスのすべての依存関係は、すべての機能によって消費される必要がありますか?つまり、異なる機能のビットが異なる依存関係を使用する場合、これらはおそらく別々のクラスに存在するはずです。

答えて

3

工assが内部状態を維持しない、またはそれだけで機能のさまざまな部分を「組み立てる」されますか?あなたはそれをそのように書き直すことができ:この場合

internal class SomeClass 
{ 
    ... 


    internal string SomeFunctionality(IDependency _someDependency) 
    { 
    ... 
    } 

    internal string OtherFunctionality(IDependency2 _someDependency2) 
    { 
    ... 
    } 
} 

をSomeFunctionalityとOtherFunctionalityは何とか(機能的に)プレースホルダを使用して明らかではないこれに関連している場合は、SRPを壊さないことがあります。

また、作成/ DI時ではなく、クライアントから使用する依存関係を選択できるという付加価値があります。おそらく、これらのメソッドのユースケースを定義するテストによって、状況を明確にするのに役立ちます。両方のメソッドが同じオブジェクトで呼び出された意味のあるテストケースを記述できる場合は、SRPを中断しません。

ファサードパターンについては、50回以上のメソッドクラスになったときに、あまりにも多くの時間がそれを気に入っているのを見てきました...質問は:なぜそれが必要なのですか?古いタイマーEJBの効率の理由から?

+0

これは依存関係が状態の概念を持たず、機能をカプセル化しているので私の問題を解決します(私はこれを私の質問 - しかしそれは当時考慮しなかった) – jpoh

0

私は通常、クラスにカプセル化できる状態の共有ピースを使用する場合、メソッドをクラスにグループ化します。クラス内のすべてのメソッドで使用されていない依存関係は、コードの匂いになりますが、非常に強いものではありません。私は通常、クラスが大きすぎるとクラスからメソッドを分割するだけです。クラスはあまりにも多くの依存関係を持っているか、メソッドが共有状態を持っていません。

0

私の質問:クラスのすべての依存関係は、すべての機能によって消費されるはずです。つまり、機能のビットが異なる場合、依存関係は別々のクラスになるはずです。

それはあなたのクラスは少し支離滅裂(「ただ一つのこと以上のものをやって」)であり得ることを示している、ヒントですが、あなたが言うように、あなたはあまりにも遠くにこれを取る場合、あなたは新しいクラスで終わります新しい機能ごとにだから、あなたはファサードオブジェクトを再び一緒に引っ張ることを望んでいるでしょう(ファサードオブジェクトはまさにこの特定のデザインルールの反対です)。

あなたとあなたのチームの残りの部分に適した良いバランスを見つける必要があります。

+0

ファサードがこのルールの反対であると思う人がいると聞いてみたいと思うでしょう – Calanus

0

私に過負荷のように見えます。 あなたは何かをしようとしており、それを行うには2通りの方法があります。 SomeClassレベルでは、作業を行うための依存関係が1つあります。その1つの依存クラスが、相互排他的な入力パラメータを使用して同じことを行う2つ(またはそれ以上)の方法をサポートするようにします。 言い換えれば、私はSomeClassと同じコードを持っていますが、代わりにSomeWorkとして定義し、他の無関係のコードは含めません。

HTH

0

ファサードは、(レガシーシステムへのインターフェイスのような)複雑さを隠す場合や、インターフェイスの観点から下位互換性を保って機能を統合したい場合に使用されます。

あなたの場合の鍵は、同じクラスに2つの異なるメソッドがある理由です。集約のように無関係なコードで実装されていても、同様のタイプの動作をグループ化するクラスを持つという意図です。あるいは、同じ振る舞いをサポートしようとしていますが、詳細に応じて別の実装があります。これは、継承/過負荷のソリューションのヒントになります。

問題は、このクラスがどんな方向に成長し続けるかどうかです。 2つの方法で違いはありませんが、3以上の繰り返しでは、ファサード/アダプターとして宣言するか、バリエーションの子クラスを作成する必要があるかを判断する必要があります。

あなたの疑惑は正しいですが、匂いは燃えているエバーからの煙だけです。あなたはそれが目に見えるようにする必要があります、それは火災が発生した場合、火災が制御不能になる前に消火する方法を決定する必要があります。

11

すべてのインスタンスメソッドがすべてのインスタンス変数に接触すると、クラスは最大限に凝集します。インスタンスメソッドが他のものとインスタンス変数を共有しない場合、そのクラスは最小限の結束性を持ちます。結束が高いことが本当であることは事実ですが、80-20の規則が適用されることも真です。結束の最後の少しの増加を取得するには、mamothの努力が必要かもしれません。

一般に、いくつかの変数を使用しないメソッドがある場合、それは匂いです。しかし、小さな匂いではクラスを完全にリファクタリングするには不十分です。それは心配していることを心配することですが、私はすぐに行動することをお勧めしません。

関連する問題