私の現在のアプリケーションでは、ユーザーは一連の管理画面を通じてカスタム 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 の知識を持ち、インスタンスを作成する必要があります。
- 私の質問は 2 つあります。求めているコンポーザビリティを達成するためのより良い方法はありますか? (おそらく、IoC コンテナーまたはホーム ロール ファクトリを使用して、具体的な IFormViewCreator を作成します)?
- ここで抽象化を根本的に台無しにしましたか?