15

私の現在のアプリケーションでは、ユーザーは一連の管理画面を通じてカスタム Web フォームを定義できます。これは本質的に EAV タイプのアプリケーションです。そのため、特定のページをレンダリングするために HTML または ASP.NET マークアップをハード コードすることはできません。代わりに、UI はサービス レイヤーから Form オブジェクトのインスタンスを要求し、サービス レイヤーは複数の RDMBS テーブルを使用してフォーム オブジェクトを構築します。フォームには、そのようなコンテキストで表示されると予想される種類のクラスが含まれています: Form=> IEnumerable<FormSections>=>IEnumerable<FormFields>

サービス層は次のようになります。

public class MyFormService: IFormService{

       public Form OpenForm(int formId){
          //construct and return a concrete implementation of Form 
       }
}

すべてが見事に機能します(しばらくの間)。UI は、特定のフォームにどのセクション/フィールドが存在するかについて賢明ではありません。受信した Form オブジェクトを、機能する ASP.NET ページに喜んでレンダリングします。

数週間後、私はビジネスから新しい要件を受け取りました。フォームの編集不可 (読み取り専用) バージョンを表示する場合、特定のフィールド値を一緒にマージし、その他の人為的/計算されたフィールドを追加する必要があります。私が言う問題はありません。メソッドがより明示的になるようにサービス クラスを修正するだけです。

public class MyFormService: IFormService{

       public Form  OpenFormForEditing(int formId){
          //construct and return a concrete implementation of Form 
       }

       public Form  OpenFormForViewing(int formId){
          //construct and a concrete implementation of Form  
          //apply additional transformations to the form
       }
}

再びすべてがうまく機能し、力のバランスが回復しました。UI は引き続きフォームの内容にとらわれず、関心の分離が達成されます。しかし、ほんの数週間後、ビジネスは新しい要件を提示しました。特定のシナリオでは、上記で参照したフォーム変換の一部のみを適用する必要があります。

この時点で、メソッド (OpenFormViewingScenario1、OpenFormViewingScenario2 など) を急増させたくない限り、「明示的なメソッド」アプローチは行き止まりに達したように感じます。代わりに、別のレベルの間接化を導入します。

public interface IFormViewCreator{
        void CreateView(Form form);
}

public class MyFormService: IFormService{

       public Form  OpenFormForEditing(int formId){
          //construct and return a concrete implementation of Form 
       }

       public Form  OpenFormForViewing(int formId, IFormViewCreator formViewCreator){
          //construct a concrete implementation of Form  
          //apply transformations to the dynamic field list
           return formViewCreator.CreateView(form);
       }
}

表面的には、これは許容できるアプローチのように見えますが、特定の臭いがあります。つまり、OpenFormForViewing の実装の詳細について無知な至福の中で生きてきた UI は、IFormViewCreator の知識を持ち、インスタンスを作成する必要があります。

  1. 私の質問は 2 つあります。求めているコンポーザビリティを達成するためのより良い方法はありますか? (おそらく、IoC コンテナーまたはホーム ロール ファクトリを使用して、具体的な IFormViewCreator を作成します)?
  2. ここで抽象化を根本的に台無しにしましたか?
4

2 に答える 2

9

質問を理解しているので、UIレイヤーに送信する前にフォームを変更する必要があります。デコレーターが配置されているように思えます。IFormViewCreator を使用せずに、古い IFormService インターフェイスを保持します。

目的のフィルタリングまたは変更を実装する 1 つ以上の装飾 FormService を作成できるようになりました。

public class MyDecoratingFormService : IFormService
{
    private readonly IFormService formService;

    public MyDecoratingFormService(IFormService formService)
    {
        if(formService == null)
        {
            throw new ArgumentNullException("formService");
        }

        this.formService = formService;
    }

    public Form OpenFormForEditing(int formId)
    {
        var form = this.formService.OpenFormForEditing(formId);
        return this.TransformForm(form);
    }   

    public Form OpenFormForViewing(int formId)
    {
        var form = this.formService.OpenFormForViewing(formId);
        return this.TransformForm(form);
    }

    public Form TransformForm(Form form)
    {
        // Implement transformation/filtering/modification here
    }
}

このようなデコレータを 1 つ以上使用して、元の IFormService 実装を装飾できるようになりました。

IFormService formService = new MyDecoratingFormService(new MyFormService());

必要な数のデコレーター (それぞれが独自の責任を持つ) を相互にラップできます。

これを実行するために DI コンテナーが明示的に必要というわけではありませんが、他の DI パターンとうまく適合します。私は常にデコレーターを使用しています:)

于 2010-01-28T08:42:03.180 に答える
0

メソッド(OpenFormViewingScenario1、OpenFormViewingScenario2など)の爆発で終わりたくない場合を除きます。

要件固有の複雑さを取り除くことはできません。いずれにせよ、ユースケースを検出し、それに応じて行動する必要があります。

可能であれば、すべての可能な組み合わせをリストするか、処理をインテリジェントに除外することができます。たとえば、要件の性質上、N * M = X可能性がある場合、メソッドを網羅的にリストXすることは実際には良くありません。とケースXの構成から可能なフォームを作成する必要があるので、因数分解する必要があります。NM

正確な要件を知らなければ、なんとも言えません。次に、このような構成を因数分解する方法は多数あります。たとえば、DecoratorChainOfResponsabilityFilterなどです。これらはすべて、複雑なロジックを構成する方法です。

つまり、OpenFormForViewing の実装の詳細について無知な至福の中で生きていた UI は、IFormViewCreator のインスタンスを認識して作成する必要があります。

プレゼンテーションは、フォームの作成にとらわれないように、別の場所で作成されたフォームを配布する必要があります。ただし、フォームはどこかで組み立て/作成する必要があります。

MVC では、モデル/フォームを更新し、正しいビュー/レンダリングにディスパッチするようなロジックがコントローラーに入ります。ASP.NETでも同じことができます

于 2010-02-09T10:28:58.560 に答える