Supongamos que tengo varias entidades en mi modelo (usando EF), como Usuario, Producto, Factura y Pedido.
Estoy escribiendo un control de usuario que puede imprimir los resúmenes de objetos de entidad en mi aplicación donde las entidades pertenecen a un conjunto predeterminado, en este caso digo que se pueden resumir resúmenes de Usuario y Producto.
Todos los resúmenes solo tendrán un ID y una descripción, así que creo una interfaz simple para esto:
public interface ISummarizableEntity {
public string ID { get; }
public string Description { get; }
}
Luego, para las entidades en cuestión, creo una clase parcial que implementa esta interfaz:
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 esta manera, mi control de usuario / vista parcial puede unirse a cualquier colección de ISummarizableEntity y no necesita estar interesado en la fuente. Me han dicho que las interfaces no deben usarse como tipos de datos, pero no obtuve más información que eso. Por lo que puedo ver, aunque las interfaces normalmente describen el comportamiento, el solo uso de propiedades no es un antipatrón en sí mismo, ya que las propiedades son solo azúcar sintáctica para captadores / establecedores de todos modos.
Podría crear un tipo de datos concreto y un mapa de las entidades a eso, pero no puedo ver el beneficio. Podría hacer que los objetos de entidad hereden de una clase abstracta y luego definir las propiedades, pero luego estoy bloqueando las entidades para que no se usen más, ya que no podemos tener herencia múltiple. También estoy dispuesto a que cualquier objeto sea ISummarizableEntity si quisiera (obviamente cambiaría el nombre de la interfaz)
La solución que estoy usando en mi mente es mantenible, extensible, comprobable y bastante robusta. ¿Puedes ver el antipatrón aquí?
EntitySummary
,User
yProduct
cada uno con un método comopublic EntitySummary GetSummary()
?Respuestas:
Las interfaces no describen el comportamiento. Todo lo contrario, a veces.
Las interfaces describen contratos, como "si voy a ofrecer este objeto a cualquier método que acepte una entidad ISummarizableEntity, este objeto debe ser una entidad que pueda resumirse a sí misma", en su caso, que se define como capaz de devolver un ID de cadena y una descripción de cadena.
Ese es un uso perfecto de las interfaces. No hay antipatrón aquí.
fuente
List
que no se comporta como una lista?Ha elegido la mejor ruta para este diseño porque está definiendo un tipo específico de comportamiento que se requerirá de varios tipos de objetos diferentes. La herencia en este caso implicaría una relación común entre las clases que en realidad no existe. En este caso, la componibilidad se ve favorecida sobre la herencia.
fuente
Las interfaces que solo tienen propiedades deben evitarse ya que:
Aquí estás mezclando dos preocupaciones:
Se hace un resumen de dos cadenas: una identificación y una descripción. Estos son datos simples:
Ahora que ha definido qué es un resumen, desea definir un contrato:
Tenga en cuenta que el uso de inteligencia en getters es un antipatrón y debe evitarse: en su lugar, debe ubicarse en funciones. Así es como se ven las implementaciones:
fuente