3

すべての派生クラスにアクセスさせたいサービス (セキュリティ オブジェクトやリポジトリなど) を持つクラスがある場合は、次のようにします。

public abstract class A
{
    static ISecurity _security;
    public ISecurity Security { get { return _security; } }

    public static void SetSecurity(ISecurity security) { _security = security; }
}

public class Bootstrapper
{
    public Bootstrapper()
    {
        A.SetSecurity(new Security());
    }
}

最近、絶対に避けるべきものとして、静的プロパティがどこでも避けられているのを見ているようです。私には、これは、作成するすべての派生クラスのコンストラクターに ISecurity パラメーターを追加するよりもきれいに思えます。最近読んだすべてのことを考えると、私は疑問に思っています:

これは依存性注入の許容可能なアプリケーションですか、それとも後で私を悩ませる可能性のある主要な設計原則に違反していますか? この時点で単体テストを行っていないので、そうであれば、質問に対する答えに突然気付くでしょう。正直なところ、おそらくそれ以上デザインを変更することはありませんが、変更する必要がある他の重要な理由がある場合は、変更する可能性があります.

編集:最初にそのコードを書いたときにいくつかの愚かな間違いを犯しました...それは今修正されました。誰かがたまたま気づいた場合に備えて、それを指摘したいと思いました:)

編集:SWekoは、すべての派生クラスが同じ実装を使用する必要があることについて良い点を指摘しています。この設計を使用した場合、サービスは常にシングルトンであるため、既存の要件が効果的に適用されます。当然、そうでない場合、これは悪い設計になります。

4

2 に答える 2

2

この設計は、いくつかの理由で問題になる可能性があります。

単体テストについてはすでに言及していますが、これはかなり重要です。このような静的な依存関係は、テストを非常に難しくする可能性があります。偽物がNull オブジェクトISecurityの実装以外のものでなければならない場合、テストの破棄時に偽物の実装を削除する必要があることに気付くでしょう。テストの破棄中にそれを削除すると、その偽のオブジェクトを削除するのを忘れたときに他のテストが影響を受けるのを防ぐことができます。テストの破棄により、テストがより複雑になります。それほど複雑ではありませんが、多くのテストにティア ダウン コードが含まれていると、これが追加され、1 つのテストがティア ダウンを実行するのを忘れると、テスト スーツのバグを見つけるのに苦労することになります。また、登録されていることを確認する必要があります。ISecurity偽のオブジェクトはスレッドセーフであり、並行して実行される可能性のある他のテストに影響を与えません (パフォーマンス上の理由から、MSTest などのテスト フレームワークは並行してテストを実行します)。

依存関係を静的として注入することで考えられるもう 1 つの問題は、このISecurity依存関係を強制的にシングルトンにする (そしておそらくスレッドセーフにする) ことです。これにより、たとえば、シングルトンとは異なるライフスタイルを持つインターセプターとデコレーターを適用できなくなります

もう 1 つの問題は、この依存関係をコンストラクターから削除すると、ユーザーに代わって DI フレームワークによって実行される分析や診断が無効になることです。この依存関係を手動で設定したため、フレームワークはこの依存関係について認識していません。ある意味では、依存関係を一緒に配線する方法をコンポジション ルートが制御できるようにするのではなく、依存関係を管理する責任をアプリケーション ロジックに戻します。ここで、アプリケーションはそれISecurityが実際にスレッドセーフであることを認識しなければなりません。これは、一般に構成ルートに属する責任です。

この依存関係を基本型に格納したいという事実は、一般的な設計原則である単一責任原則(SRP) に違反していることを示している可能性さえあります。過去に自分で犯した設計ミスと似ています。基本クラスからすべて継承された一連のビジネス オペレーションがありました。この基本クラスは、トランザクション管理、ロギング、監査証跡、フォールト トレランスの追加、セキュリティ チェックの追加など、あらゆる種類の動作を実装しました。この基本クラスは、手に負えない神オブジェクトになりました。責任が多すぎるという理由だけで、それは手に負えませんでした。SRPに違反しています。これについてもっと知りたい場合は、ここに私の話があります。

したがって、このセキュリティ上の問題 (おそらく分野横断的な問題) を基本クラスに実装する代わりに、基本クラスをまとめて削除し、デコレータを使用してそれらのクラスにセキュリティを追加してみてください。各クラスを 1 つ以上のデコレータでラップでき、各デコレータは 1 つの特定の問題を処理できます。これにより、各デコレータ クラスは SRP に従うため、簡単に理解できます。

于 2013-01-31T13:58:34.993 に答える
1

問題は、クラスの定義にカプセル化されていても、実際には依存性注入ではないことです。確かに、

static Security _security;

よりも悪いですSecurityが、それでも、 のインスタンスはA、呼び出し元が渡したセキュリティを使用できず、静的プロパティのグローバル設定に依存する必要があります。

私が言おうとしているのは、あなたの使用法は次のものとそれほど変わらないということです:

public static class Globals
{
   public static ISecurity Security {get; set;}
}    
于 2013-01-31T12:22:20.903 に答える