Tenga en cuenta la métrica de estabilidad de Martin y lo que quiere decir con "estabilidad":
Instability = Ce / (Ca+Ce)
O:
Instability = Outgoing / (Incoming+Outgoing)
Es decir, un paquete se considera completamente inestable si todas sus dependencias son salientes: usa otras cosas, pero nada lo usa. En ese caso, solo tiene sentido que esa cosa sea concreta. También será el tipo de código más fácil de cambiar ya que nada más lo usa y, por lo tanto, nada más puede romperse si ese código se modifica.
Mientras tanto, cuando tienes el escenario opuesto de "estabilidad" completa con un paquete usado por una o más cosas pero no usa nada por sí solo, como un paquete central usado por el software, es cuando Martin dice que esto debería ser resumen. Eso también se ve reforzado por la parte DIP de SOLI (D), el Principio de Inversión de Dependencia, que básicamente establece que las dependencias deben fluir uniformemente hacia las abstracciones para el código de bajo y alto nivel.
Es decir, las dependencias deberían fluir uniformemente hacia la "estabilidad", y más precisamente, las dependencias deberían fluir hacia paquetes con más dependencias entrantes que las dependencias salientes y, además, las dependencias deberían fluir hacia abstracciones. La esencia de la razón detrás de eso es que las abstracciones proporcionan espacio para respirar para sustituir un subtipo por otro, ofreciendo ese grado de flexibilidad para que las partes concretas que implementan la interfaz cambien sin romper las dependencias entrantes a esa interfaz abstracta.
¿Existen desventajas significativas al depender de abstracciones?
Bueno, en realidad no estoy de acuerdo con Martin aquí para mi dominio al menos, y aquí necesito introducir una nueva definición de "estabilidad" como en "falta de razones para cambiar". En ese caso, diría que las dependencias deberían fluir hacia la estabilidad, pero las interfaces abstractas no ayudan si las interfaces abstractas son inestables (según mi definición de "inestable", ya que son propensas a ser cambiadas repetidamente, no las de Martin). Si los desarrolladores no pueden corregir las abstracciones y los clientes cambian de opinión repetidamente de manera que los intentos abstractos de modelar el software sean incompletos o ineficaces, entonces ya no nos beneficiamos de la flexibilidad mejorada de las interfaces abstractas para proteger el sistema contra cambios en cascada que rompen la dependencia . En mi caso personal, he encontrado motores ECS, como los que se encuentran en los juegos AAA,lo más concreto : hacia datos en bruto, pero dichos datos son altamente estables (como en "es improbable que sea necesario cambiar"). A menudo he encontrado que la probabilidad de que algo que requiera cambios futuros sea una métrica más útil que la relación de acoplamientos eferentes a totales en las decisiones orientadoras de SE.
Así que alteraría un poco el DIP y solo diría, "las dependencias deberían fluir hacia los componentes que tienen la menor probabilidad de requerir más cambios", independientemente de si esos componentes son interfaces abstractas o datos sin procesar. Lo único que me importa es la probabilidad de que puedan requerir cambios directos que rompan el diseño. Las abstracciones solo son útiles en este contexto de estabilidad si algo, al ser abstracto, reduce esa probabilidad.
Para muchos contextos, ese podría ser el caso de ingenieros y clientes decentes que anticipan las necesidades del software por adelantado y diseñan abstracciones estables (como inmutables), mientras que esas abstracciones les ofrecen todo el respiro que necesitan para intercambiar implementaciones concretas. Pero en algunos dominios, las abstracciones pueden ser inestables y propensas a ser inadecuadas, mientras que los datos requeridos por el motor pueden ser mucho más fáciles de anticipar y estabilizar por adelantado. Entonces, en esos casos, en realidad puede ser más beneficioso desde el punto de vista de la mantenibilidad (la facilidad de cambiar y extender el sistema) para que las dependencias fluyan hacia los datos en lugar de las abstracciones. En un ECS, las partes más inestables (como en las partes que se cambian con mayor frecuencia) son típicamente la funcionalidad que reside en los sistemas (PhysicsSystem
, por ejemplo), mientras que las partes más estables (como las menos susceptibles de ser cambiadas) son los componentes que solo consisten en datos sin procesar ( MotionComponent
por ejemplo,) que utilizan todos los sistemas.