Supposons que j'ai plusieurs entités dans mon modèle (en utilisant EF), par exemple Utilisateur, Produit, Facture et Commande.
J'écris un contrôle utilisateur qui peut imprimer les résumés des objets entité dans mon application où les entités appartiennent à un ensemble prédéterminé, dans ce cas, je dis que les résumés utilisateur et produit peuvent être résumés.
Les résumés n'auront tous qu'un ID et une description, donc je crée une interface simple pour cela:
public interface ISummarizableEntity {
public string ID { get; }
public string Description { get; }
}
Ensuite, pour les entités en question, je crée une classe partielle qui implémente cette interface:
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); }
}
}
De cette façon, mon contrôle utilisateur / vue partielle peut simplement se lier à n'importe quelle collection de ISummarizableEntity et n'a pas besoin d'être intéressé par la source. On m'a dit que les interfaces ne devraient pas être utilisées comme types de données, mais je n'ai pas obtenu plus d'informations que cela. Pour autant que je puisse voir, bien que les interfaces décrivent normalement le comportement, le simple fait d'utiliser des propriétés n'est pas un anti-modèle en soi, car les propriétés ne sont que du sucre syntaxique pour les getters / setters de toute façon.
Je pourrais créer un type de données concret et une carte des entités à cela, mais je ne vois pas l'avantage. Je pourrais faire en sorte que les objets entité héritent d'une classe abstraite, puis définir les propriétés, mais je verrouille ensuite les entités pour qu'elles ne soient plus utilisées car nous ne pouvons pas avoir d'héritage multiple. Je suis également ouvert à ce que tout objet soit ISummarizableEntity si je le voulais (évidemment, je renommerais l'interface)
La solution que j'utilise dans mon esprit est maintenable, extensible, testable et assez robuste. Pouvez-vous voir l'anti-modèle ici?
EntitySummary
, avecUser
etProduct
chacun ayant une méthode commepublic EntitySummary GetSummary()
?Réponses:
Les interfaces ne décrivent pas le comportement. Bien au contraire, parfois.
Les interfaces décrivent des contrats, tels que "si je dois proposer cet objet à une méthode qui accepte une entité ISummarizable, cet objet doit être une entité capable de se résumer" - dans votre cas, cela est défini comme étant capable de renvoyer un ID de chaîne et description de chaîne.
C'est une utilisation parfaite des interfaces. Pas d'anti-motif ici.
la source
List
qui ne se comporte pas comme une liste?Vous avez choisi le meilleur chemin pour cette conception car vous définissez un type de comportement spécifique qui sera requis pour plusieurs types d'objets différents. L'hérédité dans ce cas impliquerait une relation commune entre les classes qui n'existe pas réellement. Dans ce cas, la composabilité est préférée à l'héritage.
la source
Les interfaces qui ne portent que des propriétés doivent être évitées car:
Ici, vous mélangez deux préoccupations:
Un résumé est composé de deux chaînes: un identifiant et une description. Ce sont des données simples:
Maintenant que vous avez défini ce qu'est un résumé, vous voulez définir un contrat:
Notez que l'utilisation de l'intelligence dans les getters est un anti-modèle et doit être évitée: elle doit plutôt être localisée dans les fonctions. Voici à quoi ressemblent les implémentations:
la source