8

私はMVC3、Entity Framework v4.3 Code First、およびSimpleInjectorを使用しています。私はこのように見えるいくつかの簡単なクラスを持っています:

public class SomeThing
{
    public int Id { get; set; }
    public string Name { get; set; }
}

次のような別のエンティティがあります。

public class MainClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual AThing AThingy { get; set; }
    public virtual BThing BThingy { get; set; }
    public virtual CThing CThingy { get; set; }
    public virtual DThing DThingy { get; set; }
    public virtual EThing EThingy { get; set; }
}

各Thingy(現在)には、次のような独自のManagerクラスがあります。

public class SomeThingManager
{
    private readonly IMyRepository<SomeThing> MyRepository;

    public SomeThingManager(IMyRepository<SomeThing> myRepository)
    {
        MyRepository = myRepository;
    }
} 

その結果、私のMainControllerは次のようになります。

public class MainController
{
    private readonly IMainManager MainManager;
    private readonly IAThingManager AThingManager;
    private readonly IBThingManager BThingManager;
    private readonly ICThingManager CThingManager;
    private readonly IDThingManager DThingManager;
    private readonly IEThingManager EThingManager;

    public MainController(IMainManager mainManager, IAThingManager aThingManager, IBThingManager bThingManager, ICThingManager cThingManager, IDThingManager dThingManager, IEThingManager eThingManager)
    {
        MainManager = mainManager;
        AThingManager = aThingManager;
        BThingManager = bThingManager;
        CThingManager = cThingManager;
        DThingManager = dThingManager;
        EThingManager = eThingManager;
    }

    ...various ActionMethods...
}

実際には、このコントローラーには2倍の数の依存関係が注入されています。臭い。すべてまたはほとんど同じ依存関係を持つOtherControllerがあることも知っていると、匂いはさらに悪化します。リファクタリングしたい。

私はすでにDIについて十分に知っているので、プロパティインジェクションとサービスロケーターは良いアイデアではありません。

MainControllerは単一の画面であるため、これらすべてを表示して、1つの[保存]ボタンをクリックするだけで編集できるようにする必要があるため、MainControllerを分割できません。言い換えれば、単一の投稿アクションメソッドはすべてを保存します(ただし、それが単一の[保存]ボタンである限り、それが理にかなっている場合は変更してもかまいません)。この画面はKnockoutjsで構築されており、違いが生じる場合はAjaxの投稿とともに保存されます。

私はアンビエントコンテキストの使用をユーモアを交えましたが、それが正しい方法であるとは確信していません。私はファサードを注入することの使用もユーモアを交えました。また、この時点でコマンドアーキテクチャを実装する必要があるかどうかも疑問に思っています。(上記のすべてが匂いを別の場所に移動するだけではありませんか?)

最後に、おそらく上記の3つのアプローチとは関係なく、代わりに、GetAThings()、GetAThing(id)、GetBThings()、GetBThing(id)などの明示的なメソッドを持つLookupManagerを1つ持つ必要がありますか?(ただし、そのLookupManagerには、いくつかのリポジトリー、または新しいタイプのリポジトリーを挿入する必要があります。)

私の考えはさておき、私の質問は、繰り返しますが、このコードをリファクタリングして、注入された依存性の狂った数を減らすための良い方法は何ですか?

4

3 に答える 3

4

作業単位のデザインパターンの使用を検討しましたか?作業単位とは何かについてのすばらしいMSDN投稿があります。その記事からの抜粋:

ある意味で、作業単位はすべてのトランザクション処理コードをダンプする場所と考えることができます。作業単位の責任は次のとおりです。

  • トランザクションを管理します。
  • データベースの挿入、削除、および更新を注文します。
  • 重複する更新を防ぎます。Unit of Workオブジェクトの単一の使用法の中で、コードの異なる部分が同じInvoice
    オブジェクトを変更済みとしてマークする場合がありますが、UnitofWorkクラスは
    データベースに対して単一のUPDATEコマンドのみを発行します。

作業単位パターンを使用することの価値は、コードの残りの部分をこれらの懸念から解放し、それ以外の場合はビジネスロジックに集中できるようにすることです。

これについてはいくつかのブログ投稿がありますが、私が見つけた最高のものは、それを実装する方法についてですこのサイトからここ、そしてここで参照されているものが他にもいくつかあります。

最後に、おそらく上記の3つのアプローチとは関係なく、代わりに、GetAThings()、GetAThing(id)、GetBThings()、GetBThing(id)などの明示的なメソッドを持つLookupManagerを1つ持つ必要がありますか?(ただし、そのLookupManagerには、いくつかのリポジトリー、または新しいタイプのリポジトリーを挿入する必要があります。)

特に、データベース処理のニーズのほとんどに対応する汎用リポジトリーを実装できる場合は、作業単位でこれらすべてを処理できます。あなたのタグは、Entity Framework 4.3を使用していることを示していますよね?

お役に立てれば!

于 2012-08-21T01:04:44.107 に答える
4

コマンド アーキテクチャを使用することは良い考えです。これにより、すべてのビジネス ロジックがコントローラーの外に移動し、コードを変更せずに分野横断的な問題を追加できるようになります。ただし、これはコンストラクターの過剰注入の問題を解決しません。標準的な解決策は、関連する依存関係を集約サービスに移動することです。ただし、作業単位パターンを確認する必要があるというマークに同意します。

于 2012-08-21T07:32:10.077 に答える
0

あなたの主な問題は、抽象化レイヤーが多すぎることだと思います。Entity Frameworkを使用しているため、データの周りにすでに抽象化レイヤーがあり、リポジトリを介してさらに2つのレイヤー(エンティティごとに1つ)を追加すると、マネージャーインターフェイスによってコントローラーが依存するインターフェイスが多数発生します。それはそれほど多くの価値を追加しません、そしてその上、YAGNI

リファクタリングして、リポジトリとマネージャーレイヤーを取り除き、「アンビエントコンテキスト」を使用します。

次に、コントローラーがマネージャーレイヤーに要求しているクエリの種類を確認します。これらが非常に単純な場合、コントローラーで直接「アンビエントコンテキスト」をクエリすることに問題はありません。これが私が行うことです。より複雑な場合は、これを新しいインターフェイスにリファクタリングし、論理的にグループ化して(必ずしもエンティティごとに1つである必要はありません)、IOCを使用します。

于 2012-08-21T01:11:52.677 に答える