Quizás haya notado que la gente dice esto en los últimos meses, pero los buenos programadores lo saben desde hace mucho más tiempo. Ciertamente lo he estado diciendo cuando sea apropiado durante aproximadamente una década.
El punto del concepto es que hay una gran sobrecarga conceptual para la herencia. Cuando usa la herencia, cada llamada de método tiene un despacho implícito. Si tiene árboles de herencia profundos, o despacho múltiple, o (aún peor) ambos, entonces averiguar dónde se enviará el método en particular en cualquier llamada en particular puede convertirse en un PITA real. Hace que el razonamiento correcto sobre el código sea más complejo y dificulta la depuración.
Permítanme dar un ejemplo simple para ilustrar. Supongamos que en el fondo de un árbol de herencia, alguien nombra un método foo
. Entonces alguien más aparece y agrega foo
en la parte superior del árbol, pero haciendo algo diferente. (Este caso es más común con la herencia múltiple). Ahora esa persona que trabaja en la clase raíz ha roto la oscura clase secundaria y probablemente no se da cuenta. Podría tener una cobertura del 100% con las pruebas unitarias y no notar esta ruptura porque la persona en la parte superior no pensaría en probar la clase infantil, y las pruebas para la clase infantil no piensan en probar los nuevos métodos creados en la parte superior . (Es cierto que hay formas de escribir pruebas unitarias que captarán esto, pero también hay casos en los que no es fácil escribir pruebas de esa manera).
Por el contrario, cuando usa la composición, en cada llamada generalmente es más claro a qué está enviando la llamada. (De acuerdo, si está utilizando la inversión de control, por ejemplo, con la inyección de dependencia, averiguar dónde va la llamada también puede ser problemático. Pero, por lo general, es más sencillo de resolver). Esto facilita el razonamiento al respecto. Como beneficio adicional, la composición da como resultado que los métodos estén separados entre sí. El ejemplo anterior no debería suceder allí porque la clase secundaria pasaría a algún componente oscuro, y nunca hay una pregunta sobre si la llamada a foo
estaba destinada al componente oscuro o al objeto principal.
Ahora tiene toda la razón en que la herencia y la composición son dos herramientas muy diferentes que sirven a dos tipos diferentes de cosas. La herencia segura conlleva una sobrecarga conceptual, pero cuando es la herramienta adecuada para el trabajo, conlleva menos sobrecarga conceptual que tratar de no usarla y hacer a mano lo que hace por usted. Nadie que sepa lo que está haciendo diría que nunca debes usar la herencia. Pero asegúrese de que sea lo correcto.
Desafortunadamente, muchos desarrolladores aprenden sobre software orientado a objetos, aprenden sobre herencia y luego salen a usar su nuevo hacha con la mayor frecuencia posible. Lo que significa que intentan usar la herencia donde la composición era la herramienta correcta. Esperemos que aprendan mejor a tiempo, pero con frecuencia esto no sucede hasta después de quitar algunas extremidades, etc. Decirles por adelantado que es una mala idea tiende a acelerar el proceso de aprendizaje y reducir las lesiones.