¿Cómo sabemos que favorecer la composición sobre la generalización es siempre la elección correcta?


9

Ya sea que un objeto exista físicamente o no, podemos elegir modelarlo de diferentes maneras. Podríamos usar arbitrariamente generalización o composición en muchos casos. Sin embargo, el principio de GoF de "favorecer la composición sobre la generalización [sic]" nos guía a usar la composición. Entonces, cuando modelamos, por ejemplo, una línea, creamos una clase que contiene dos miembros PointA y PointB del tipo Point (composición) en lugar de extender Point (generalización). Este es solo un ejemplo simplificado de cómo podemos elegir arbitrariamente la composición o la herencia para modelar, a pesar de que los objetos suelen ser mucho más complejos.

¿Cómo sabemos que esta es la elección correcta? ¿Importa al menos porque podría haber una tonelada de refactorización si está mal?


99
Su ejemplo realmente no funciona porque no puede decir que una línea es un punto y, por lo tanto, falla el Principio de sustitución de Liskov y la herencia no es apropiada.
Dean Harding

@Dean: Como probablemente sepa, el ejemplo no es central para señalar. Para el registro, una línea se puede representar como una ecuación definida a través de dos puntos.
CarneyCode


1
@Songo: Parece que te has perdido totalmente el punto.
CarneyCode

¿No se está extendiendo la especialización en lugar de la generalización?
Tulains Córdova

Respuestas:


17

No siempre es la elección correcta. Es el favorable en la mayoría de los casos. Cuando un modelo compuesto requiere cambio o extensión, es considerablemente más resistente a eso porque puede cambiar la composición sin temor a afectar a otras clases sin darse cuenta.

Cómo sabemos esto? De la experiencia y la experiencia de los demás.

He visto muchas situaciones en las que una jerarquía de clases masiva ha surgido de lo que comenzó como un concepto simple, y aquí es donde su refactorización se hace necesaria. Mientras tanto, nunca he visto una situación en la que una estructura de composición necesitara ser refactorizada en herencia.

Pero mi evidencia anecdótica no debería ser suficiente. Basta con mirar en Internet y un buen número de personas ha tenido las mismas experiencias.


Me gusta Vota a favor.
CarneyCode

+1 para "Nunca he visto una situación en la que una estructura de composición necesitara ser refactorizada en herencia".
Kazark el

7

Si desea una regla general más fuerte más allá de "favorecer la composición sobre la herencia", entonces podría sugerir algo como esto:

De las dos formas de especializar un objeto (herencia y composición), debe usar la herencia solo cuando necesite que su objeto sea polimórfico (sea sustituible) para la clase base que se está especializando.

Sin embargo, como todas las reglas generales, una vez que comprenda la regla, entonces es libre de romperla :)


0

No veo cómo la composición y la generalización son alternativas y no pude encontrar la cita .
La composición y la herencia son (para lograr la especialización), y se puede argumentar, que la abstracción y la generalización son (para lograr la modularidad).

Lo que desea es que su diseño sea simple y plausible, que son dos cualidades que son inherentemente fáciles de medir.
En su caso, parece más plausible componer una línea de dos puntos en lugar de extenderla, porque naturalmente definiría una línea por dos puntos, en lugar de extender el concepto de un punto.


¿Es más natural? ¿Una línea no tiene más dos puntos que un solo punto extendido?
CarneyCode

2
Nunca he visto una definición de línea que no incluya el hecho de que está hecha de más de 2 puntos. Incluso usando una ecuación de una línea si solo tiene 1 x valor en su dominio de números, entonces es un punto, no una línea.
Aparejo

0

El favor ocurre cuando ambos candidatos califican. El problema planteado en la pregunta falla en esta cuenta, ya que solo tiene una opción de composición.

"La composición podría usar la generalización también". ¿Tiene sentido esta afirmación para nosotros? Si no es así, todavía no estamos listos para comprender la regla del 'favor'.

Por qué estamos a favor de la composición es que la composición ofrece más posibilidades de extensión / flexibilidad que la generalización. Esta extensión / flexibilidad se refiere principalmente a tiempo de ejecución / flexibilidad dinámica (que se logra con la combinación de interfaces y composición).

El beneficio no es inmediatamente visible. Para ver el beneficio, debe esperar la próxima solicitud de cambio inesperado. Entonces, en la mayoría de los casos, aquellos que se apegan a la generalización fallan en comparación con aquellos que adoptaron la composición (excepto un caso obvio mencionado más adelante). De ahí la regla. Desde el punto de vista del aprendizaje, si puede implementar una inyección de dependencia con éxito, entonces debe saber cuál favorecer y cuándo. La regla lo ayuda a tomar una decisión cuando no está seguro de cuál elegir. Una vez más, debería poder ver ambas opciones en primer lugar para favorecer una.

Resumen: Composición: el acoplamiento se reduce con solo tener algunas cosas más pequeñas que se conectan a algo más grande, y el objeto más grande simplemente llama al objeto más pequeño. Generlización: desde un punto de vista de API de terceros, definir que un método puede ser anulado es un compromiso más fuerte que definir que se puede llamar a un método (seguro ganar para la generalización). Y nunca olvide que con la composición también está utilizando la generalización, desde una interfaz en lugar de una gran clase. Pero todo el crédito va a la composición por desgracia.


-4

Hoy escribí alrededor de 300 LoC. Y no recuerdo ningún principio que pudiera violar y no violé. Refactorizar salvará mi alma, espero.

Si la abstracción es dictada por la API de la parte 3d, generalmente es correcto usar la herencia. En el diseño doméstico, la entidad debe ser abstracta o sellada. La entidad abstracta potencialmente debe tener unos 3 herederos. No me gustan los puntos de extensión de un método virtual. Todo lo anterior es sobre mi gusto. No estoy hablando de abstracción de interfaz, que es una historia completamente diferente.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.