Pregunta

Yo tenía una discusión en el trabajo con respecto a "Herencia en modelo de dominio está complicando la vida a los desarrolladores". Soy un programador OO, así que empecé a buscar argumentos que tiene herencia en modelo de dominio facilitará la vida del revelador en realidad en lugar de tener interruptores de todo el lugar.

Lo que me gustaría ver es la siguiente:

class Animal {

}

class Cat : Animal {

}

class Dog : Animal {

}

Lo que el otro colega está diciendo es:

public enum AnimalType {
    Unknown,
    Cat,
    Dog
}

public class Animal {

    public AnimalType Type { get; set; }

}

¿Cómo convencerlo (enlaces son BIENVENIDOS ) que una jerarquía de clases sería mejor que tener una propiedad de enumeración para este tipo de situaciones?

Gracias!

¿Fue útil?

Solución

Aquí es como razón de ello:

Sólo el uso de herencia si el papel / tipo será nunca cambian. p.ej.

utilizando la herencia de cosas como:

bombero <- Empleado <-. La persona se encuentra mal

tan pronto como el bombero Freddy cambios de trabajo o pierde su empleo, hay que matarlo y volver a crear un nuevo objeto del nuevo tipo con todas las viejas relaciones que se le atribuye.

Así que la solución ingenua al problema anterior sería dar una propiedad JobTitle enumeración a la clase de persona. Esto puede ser suficiente en algunos escenarios, por ejemplo, si no es necesario comportamientos muy complejos asociados a la función / tipo.

La forma más correcta sería la de dar a la clase persona una lista de roles. Cada rol representa por ejemplo un empleo con un lapso de tiempo.

por ejemplo.

freddy.Roles.Add(new Employement( employmentDate, jobTitle ));

o si eso es una exageración:

freddy.CurrentEmployment = new Employement( employmentDate, jobTitle );

De esta manera, Freddy puede convertirse en un desarrollador w / o que tener que matarlo primero.

Sin embargo, todas mis divagaciones todavía no han respondido si debe usar una jerarquía de enumeración o clase del jobTitle.

En puros de mem Oo yo diría que es más correcto utilizar la herencia para las jobtitles aquí.

Sin embargo, si usted está haciendo el mapeo O / R que podría terminar con un modelo de datos demasiado complejas poco detrás de las escenas si el mapeador intenta asignar cada subtipo a una nueva mesa. Por lo tanto, en tales casos, a menudo voy para el enfoque de enumeración si no hay un comportamiento real / compleja asociada con los tipos. Puedo vivir con un "tipo si == JobTitles.Fireman ..." si el uso es limitado y que hace cosas easer o menos complejo.

por ejemplo. el diseñador de Entity Framework 4 para .NET sólo se puede asignar cada subtipo a una nueva mesa. y puede obtener un modelo feo o un montón de combinaciones cuando se consulta la base de datos w / o ningún beneficio real.

Sin embargo hago uso de la herencia si el tipo / papel es estática. p.ej. para los productos.

es posible que tenga CD <- Producto y reservar <- Producto. La herencia gana aquí porque en este caso es muy probable que tenga diferente estado asociado con los tipos. CD podría tener un número de pistas propiedad mientras que un libro puede contener varias páginas de propiedad.

Así que en resumen, que depende; -)

Además, al final del día, lo más probable es terminar con una gran cantidad de sentencias switch de cualquier manera. Digamos que usted quiere editar un "producto", incluso si se utiliza la herencia, es probable que tenga un código como este:

Si (el producto es libro)         Response.Redicted ( "~ / EditBook.aspx identificación?" + Product.id);

Debido a que codifica la URL de edición de libros en la clase de entidad sería feo llano, ya que obligaría a sus negocios ENTIDADES saber sobre la estructura del sitio, etc.

Otros consejos

Las enumeraciones son buenos cuando:

  1. El conjunto de valores es fijo y nunca o muy raramente cambia.
  2. ¿Quieres ser capaz de representar una unión de valores (es decir, la combinación de banderas).
  3. No es necesario adjuntar otro estado para cada valor. (Java no tiene esta limitación.)

Si se pudiera resolver su problema con un número, una enumeración es probablemente un buen ajuste y más de tipo seguro. Si necesita más flexibilidad que el anterior, entonces es probable enumeraciones no la respuesta correcta. Utilización de las clases polimórficas, puede:

  1. estáticamente a asegurar que todo el comportamiento específico del tipo se maneja. Por ejemplo, si necesita todos los animales para poder Bark(), haciendo clases Animal con un método abstracto Bark() permitirá que el cheque compilador para usted que cada subclase que implementa. Si utiliza una enumeración y una gran switch, no se asegurará de que usted ha manejado todos los casos.

  2. Puede añadir nuevos casos (tipos de animales en el ejemplo). Esto se puede hacer a través de los archivos de origen, e incluso a través de los límites del paquete. Con una enumeración, una vez que se ha declarado en él, está congelado. extensión de composición abierta es uno de los principales puntos fuertes de la programación orientada a objetos.

Es importante tener en cuenta que el ejemplo de su colega no está en oposición directa a la suya. Si él quiere tipo de un animal para ser una propiedad expuesta (que es útil para algunas cosas), todavía se puede hacer eso sin necesidad de utilizar una enumeración con las teclas tipo modelo objeto :

public abstract class AnimalType {
    public static AnimalType Unknown { get; private set; }
    public static AnimalType Cat { get; private set; }
    public static AnimalType Dog { get; private set; }

    static AnimalType() {
        Unknown = new AnimalType("Unknown");
        Cat = new AnimalType("Cat");
        Dog = new AnimalType("Dog");
    }
}

public class Animal {
    public AnimalType Type { get; set; }
}

Esto le da la conveniencia de una enumeración: se puede hacer AnimalType.Cat y se puede obtener el tipo de un animal. Pero también le da la flexibilidad de las clases: puede añadir campos a AnimalType para almacenar datos adicionales con cada tipo, añadir métodos virtuales, etc. Más importante aún, se pueden definir nuevos tipos de animales con sólo la creación de nuevas instancias de AnimalType

me gustaría instar a que reconsidere: en una modelo de dominio (por los comentarios anteriores ), los gatos no comportan de manera diferente a los perros, así que no hay polimorfismo. Un tipo de animal es realmente sólo un atributo. Es difícil ver lo que compra de herencia allí.

Tener una enumeración es como una fiesta para todas aquellas personas Open/Closed Principle is for suckers.

Realmente le invita a comprobar si un animal es de un tipo determinado y luego se aplica la lógica personalizada para cada tipo. Y eso puede hacer que el código horrible, lo que hace que sea muy difícil continuar la construcción en su sistema.

Lo más importante OOPS mediante el modelado de la realidad. La herencia le da la oportunidad de decir el gato es un animal. Animal no debe saber si su gato ahora un grito y luego decidir que se supone que debe maullido y no raspan, encapsulación se venció allí. Código menos como ahora usted no tiene que hacer otra cosa Si como usted ha dicho.

Las dos soluciones son correctas. Usted debe mirar qué técnicas se aplica mejor a usted un problema.

Si el programa utiliza algunos objetos diferentes, y no añade nuevas clases, es mejor quedarse con las enumeraciones.

Pero si programa utiliza una gran cantidad de diferentes objetos (diferentes clases), y puede añadir nuevas clases, en el futuro, tratar mejor la forma de herencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top