モデルに(EFを使用して)さまざまなエンティティーがあるとします(ユーザー、製品、請求書、注文など)。
エンティティが事前に決定されたセットに属しているアプリケーションで、エンティティオブジェクトの概要を印刷できるユーザーコントロールを作成しています。この場合、ユーザーと製品の概要を要約できると言います。
要約にはすべてIDと説明しか含まれないため、このための簡単なインターフェースを作成します。
public interface ISummarizableEntity {
public string ID { get; }
public string Description { get; }
}
次に、問題のエンティティーについて、このインターフェースを実装する部分クラスを作成します。
public partial class User : ISummarizableEntity
{
public string ID
{
get{ return UserID.ToString(); }
}
public string Description
{
get{ return String.Format("{0} {1} is from {2} and is {3} years old", FirstName, LastName, Country, Age); }
}
}
public partial class Product: ISummarizableEntity
{
public string ID
{
get{ return ProductID.ToString(); }
}
public string Description
{
get{ return String.Format("{0} weighs {1}{2} and belongs in the {3} department", ProductName, WeightValue, WeightUnit, Department); }
}
}
このようにして、ユーザーコントロール/部分ビューはISummarizableEntityの任意のコレクションにバインドすることができ、ソースにまったく関心を持つ必要はありません。インターフェイスをデータ型として使用するべきではないと言われましたが、それ以上の情報は得られませんでした。私の知る限りでは、インターフェイスは通常動作を説明しますが、プロパティはゲッター/セッターの構文糖衣であるため、プロパティを使用すること自体はアンチパターンではありません。
具体的なデータ型を作成し、エンティティからそれにマッピングすることはできますが、メリットがわかりません。エンティティオブジェクトを抽象クラスから継承してプロパティを定義することもできますが、多重継承ができないため、エンティティをロックしてこれ以上使用できません。また、必要に応じて、オブジェクトをISummarizableEntityにすることもできます(明らかに、インターフェイスの名前を変更します)
私が心の中で使用しているソリューションは、保守、拡張、テストが可能で、かなり堅牢です。ここにアンチパターンが見えますか?
インターフェイスは動作を記述していません。まったく逆のこともあります。
インターフェイスは、「ISummarizableEntityを受け入れるメソッドにこのオブジェクトを提供する場合、このオブジェクトはそれ自体を要約できるエンティティである必要がある」などの規約を記述します-あなたの場合、それは、文字列IDと文字列Description。
これはインターフェースの完璧な使い方です。ここにはアンチパターンはありません。
複数の異なるタイプのオブジェクトに必要となる特定のタイプの動作を定義しているので、この設計により適切なパスを選択しました。この場合の継承は、実際には存在しないクラス間の共通の関係を意味します。この場合、継承よりも構成可能性が優先されます。
プロパティのみを保持するインターフェイスすべきは、次の理由から避けてください:
ここでは、2つの懸念が混在しています。
概要は、IDと説明の2つの文字列で構成されます。これは単純なデータです:
public class Summary {
private readonly string id;
private readonly string description;
public Summary(string id, string description) {
this.id = id;
this.description = description;
}
public string Id { get { return id; } }
public string Description { get { return description; } }
}
これで、契約を定義したい要約を定義しました。
public interface ISummarizableEntity {
public Summary GenerateSummary();
}
ゲッターでインテリジェンスを使用することはアンチパターンであり、避けるべきであることに注意してください。代わりに関数に配置する必要があります。実装は次のようになります。
public partial class User : ISummarizableEntity {
public Summary GenerateSummary() {
var id = UserID.ToString();
var description = String.Format("{0} {1} is from {2} and is {3} years old", FirstName, LastName, Country, Age);
return new Summary(id,description);
}
}
public partial class Product : ISummarizableEntity {
public Summary GenerateSummary() {
var id = ProductID.ToString();
var description = String.Format("{0} weighs {1}{2} and belongs in the {3} department", ProductName, WeightValue, WeightUnit, Department);
return new Summary(id,description);
}
}