Me pregunto qué es mejor en términos de buen diseño de OOP, código limpio, flexibilidad y evitar olores de código en el futuro. Situación de imagen, donde tiene muchos objetos muy similares que necesita representar como clases. Estas clases no tienen ninguna funcionalidad específica, solo clases de datos y son diferentes solo por nombre (y contexto) Ejemplo:
Class A
{
String name;
string description;
}
Class B
{
String name;
String count;
String description;
}
Class C
{
String name;
String count;
String description;
String imageUrl;
}
Class D
{
String name;
String count;
}
Class E
{
String name;
String count;
String imageUrl;
String age;
}
¿Sería mejor mantenerlos en clases separadas, para obtener una "mejor" legibilidad, pero con muchas repeticiones de código, o sería mejor usar la herencia para estar más SECO?
Al usar la herencia, terminarás con algo como esto, pero los nombres de clase perderán su significado contextual (debido a is-a, no has-a):
Class A
{
String name;
String description;
}
Class B : A
{
String count;
}
Class C : B
{
String imageUrl;
}
Class D : C
{
String age;
}
Sé que la herencia no es y no debe usarse para la reutilización del código, pero no veo ninguna otra forma posible de reducir la repetición del código en tal caso.
fuente
Exactamente. Mira esto, fuera de contexto:
¿Qué propiedades tiene una D? ¿Puedes recordar? ¿Qué pasa si complica aún más la jerarquía?
¿Y qué pasa si, horror sobre horrores, quieres agregar un campo imageUrl a F pero no E? No se puede derivar de C y E.
He visto una situación real en la que muchos tipos de componentes diferentes tenían un nombre, un ID y una descripción. Pero esto no fue por la naturaleza de sus componentes, solo fue una coincidencia. Cada uno tenía una identificación porque estaban almacenados en una base de datos. El nombre y la descripción eran para mostrar.
Los productos también tenían una identificación, nombre y descripción, por razones similares. Pero no eran componentes, ni eran productos de componentes. Nunca verías las dos cosas juntas.
Pero, algún desarrollador había leído sobre DRY y decidió que eliminaría toda pista de duplicación del código. Así que llamó a todo producto y eliminó la necesidad de definir esos campos. Se definieron en Producto y todo lo que necesitaba esos campos podría derivarse de Producto.
No puedo decir esto con suficiente fuerza: esta no es una buena idea.
DRY no se trata de eliminar la necesidad de propiedades comunes. Si un objeto no es un Producto, no lo llame Producto. Si un Producto NO REQUIERE una Descripción, por la naturaleza misma de ser un Producto, no defina la Descripción como una Propiedad del Producto.
Sucedió, eventualmente, que teníamos Componentes sin descripciones. Entonces comenzamos a tener descripciones nulas en esos objetos. No anulable. Nulo. Siempre. Para cualquier producto de tipo X ... o posterior Y ... y N.
Esta es una violación atroz del Principio de sustitución de Liskov.
DRY se trata de nunca ponerse en una posición en la que pueda corregir un error en un lugar y olvidarse de hacerlo en otro lugar. Esto no va a suceder porque tiene dos objetos con la misma propiedad. Nunca. Así que no te preocupes por eso.
Si el contexto de las clases hace obvio que debería hacerlo, lo cual será muy raro, entonces y solo entonces debería considerar una clase principal común. Pero, si se trata de propiedades, considere por qué no está utilizando una interfaz.
fuente
La herencia es la forma de lograr un comportamiento polimórfico. Si sus clases no tienen ningún comportamiento, entonces la herencia es inútil. En este caso, ni siquiera los consideraría objetos / clases, sino estructuras.
Si desea poder colocar diferentes estructuras en diferentes partes de su comportamiento, considere las interfaces con métodos / propiedades get / set, como IHasName, IHasAge, etc. Esto hará que el diseño sea mucho más limpio y permita una mejor composición de estos tipo de jerarquías.
fuente
¿No es esto para lo que son las interfaces? Clases no relacionadas con diferentes funciones pero con una propiedad similar.
fuente
Su pregunta parece estar enmarcada en el contexto de un lenguaje que no admite herencia múltiple pero que no especifica específicamente esto. Si está trabajando con un lenguaje que admite herencia múltiple, esto se vuelve trivialmente fácil de resolver con un solo nivel de herencia.
Aquí hay un ejemplo de cómo se puede resolver esto usando la herencia múltiple.
fuente