lunes, 6 de enero de 2020

Capítulo 14: acoplamiento entre componentes - Parte 3 - Clean Architecture

El principio de abstracciones estables

Un componente debe ser tan abstracto como estable.

¿Dónde se ubica la política de alto nivel?

La política de alto nivel hace referencia a los requisitos que el sistema demanda los cuales están especificados por las reglas de negocio. Estas reglas de negocio deberían estar en componentes que sean estables (I = 0). Los componentes inestables (I = 1) deberían contener políticas volátiles de manera que estas son fáciles de cambiar.

No obstante, si las políticas de alto nivel se ubican en componentes estables este código va a ser difícil de cambiar. Esto podría conllevar que las políticas de alto nivel sean difíciles de cambiar y se conviertan en algo inflexible. 

¿Cómo un componente máximamente estable (I = 0) puede ser lo suficientemente flexible como para soportar un cambio? La respuesta viene dada por el «Open-Close Principle» el cuál establece que un artefacto software debería estar abierto para extensión pero cerrado para modificación. El objetivo es crear clases que sean lo suficientemente flexibles para que se puedan extender sin requerir modificaciones. 
¿Qué tipo de clases cumplen este objetivo? Las clases abstractas. 

Introducción al principio de abstracción estable 

El «Stable Abstract  Principle» establece que un componente estable también debería ser abstracto de manera que su estabilidad no compromete su flexibilidad. 

Un componente inestable debería contener código concreto desde que su inestabilidad permite cambiar este código fácilmente.

Los componentes estables deberían estar implementados por interfaces y clases abstractas de maneras que se puedan extender. Estos componentes extensibles son lo suficientemente flexibles como para no restringir la arquitectura.

La combinación del «Stable Abstract Principle» junto con el «Stable Dependency Principle» forman el «Dependency Injection Principle» para los componentes. El «Stable Dependency Principle» establece que las dependencias deberían apuntar en dirección de la estabilidad mientras que el «Stable Abstract Principle» establece que la estabilidad implica abstracción. De esta manera, las dependencias apuntan en la dirección de la abstracción.

El «Dependency Injection Principle» hace referencia a clases y las clases son o no pero no medio son. Esto significa que una clases es abstracta o no lo es pero no es medio abstracta. No obstante, los componentes tienen un rango de estabilidad (de 0 a 1) por lo que la combinación de «Stable Dependency Principle» y el «Stable Abstract Principle» permite que los componentes puedan ser parcialmente abstractos y estables.

Midiendo la abstracción

La abstracción de un componente viene dado por el valor del ratio de interfaces y clases abstractas en el componente del total del número de clases en el componente. A esto se le denomina métrica A.
  • Nc: Número de clases en el componente.
  • Na: el número de clases e interfaces abstractos en el componente.
  • A: abstracción. A = Na / Nc.
La métrica A tiene un rango de entre 0 y 1. Un valor de 0 implica que el componente no tiene clases abstractas mientras que un valor de 1 es que contiene exclusivamente clases abstractas.

La secuencia principal

Dadas las métricas de estabilidad («I»)) y abstracción («A») se puede establecer una relación entre ellas. Para representar esta relación se va a usar un gráfico en el que el eje vertical esté definida la Abstracción mientras que en el horizontal está la estabilidad.




De este gráfico se puede inferir que los componentes que tienen máxima estabilidad y abstracción se encuentran en la esquina superior izquierda mientras que los que son Inestables y concretos están en la esquina inferior derecha.

Como se ha visto anteriormente, todos los componentes tienen un grado de estabilidad y abstracción por lo que se pueden establecer distintas zonas de el gráfico. Estas zonas se pueden ver en el siguiente gráfico.

Zona del dolor

Un componente que esté en el punto (0,0) será un componente que tenga la mínima inestabilidad y la mínima abstracción. Esto define un componente altamente estable y concreto. Este tipo de componentes no es deseable porque es rígido. No se pueden extender porque no es abstracto y es muy difícil de cambiar por su estabilidad.

Los componentes con un buen diseño no se esperan ver cerca del punto (0,0). El área cerca de este punto se denomina Zona del dolor y debería ser una zona de exclusión.

Un buen ejemplo de entidades que caen en esta zona podría ser el esquema de una base de datos. Estos esquemas son notoriamente volátiles y extremadamente concretos. Esta es la razón por la cual una interfaz entre la aplicación y la base de datos son tan difíciles de administrar y porqué su actualización es un “dolor”.

Otro ejemplo de software que se ubica en la zona podría ser una librería de utilidad concreta. A pesar de que la librería tenga una máxima inestabilidad puede que esta no sea volátil. Por ejemplo, si se tiene una librería que formatea las fechas en una aplicación esta podría ser tan comúnmente usada que cambiarla podría crear el caos por lo que esta librería no es volátil.

Los componente nos volátiles son inofensivos en la zona del dolor ya que no es probable que se cambien. Son sólo los componentes volátiles los que son problemáticos en esta zona. Cuanto más volátil es un componente más doloroso será cambiar este. En realidad, la volatilidad se podría considerar un tercer eje en el gráfico. El gráfico anterior muestra el plano más doloroso cuando la volatilidad es 1. 

Zona de inutilidad

Los componentes de esta zona tienen una abstracción máxima y no tienen otro componentes que dependan de él. Así que, como componente es inútil. Esta es la razón por la que se le llama Zona de inutilidad.

Estas entidades de software suelen ser basura que no se ha eliminado. Suelen ser clases abstractas que nadie ha implementado. 

Un componente en la zona de inutilidad tiene un porcentaje significativo de tales entidades. Obviamente, la presencia de estas entidades inútiles no es deseable.

Evitando la zona de exclusión

Parece claro que los componentes más volátiles deberían mantenerse tan lejos de las zonas de exclusión como sea posible. El lugar que está más alejado de estas dos zonas es la línea que va desde el punto (0, 1) al punto (1, 0). Robert C. Martin llama a esto la línea de «Secuencia principal».

Un componente que se ubica en la «Secuencia principal» no es demasiado abstracto para su estabilidad ni demasiado inestable para su abstracción. Este no es inútil ni particularmente doloroso. Otros son dependientes de él en la medida que es abstracto mientras y este depende de otros para extender ya es concreto.

Las posiciones más deseables para un componente es uno de los dos extremos de la línea de la «Secuencia principal». Los buenos arquitectos se esfuerzan por posicionar la mayoría de sus componentes en uno de estos dos puntos.

No obstante, Rober C. Martin apunta que bajo su experiencia algunas pequeñas fracciones de los componentes de sistemas con un tamaño grande ni son perfectamente abstractos ni son perfectamente estables. 

Los componentes que tienen las mejores características se encuentran en, o cerca, de la «Secuencia principal».

Distancia desde la línea de la Secuencia Principal

Si para los componentes es deseable que se encuentren en, o lo más cerca posible, de la «Secuencia principal» entonces se puede crear una métrica que mida cómo de lejos está el ideal.

Distancia D = |A + I -1 |
El rango de esta métrica es de 0 a 1. Un valor de 0 indica que el componente se encuentra sobre la línea de secuencia principal mientras que un valor de 1 se encuentra lo más alejado posible de la «Secuencia principal».

Dada esta métrica, un diseño se puede analizar respecto a su conformidad general sobre la «Secuencia principal». Se puede calcular la métrica D por cada componente. Cualquier componente que tenga un valor que no esté cerca de 0 se puede reexaminar y reestructurar.

También es posible el análisis estadístico de un diseño. Se puede calcular la media y la varianza de todas las métricas D para los componentes de un diseño. Nosotros podriamos esperar un diseño conforme a que este tenga una media y una varianza cercana al 0. La varianza se puede usar para establecer “límites de control” de manera que se identifiquen componentes excepcionales en comparación con el resto.

En el siguiente gráfico se puede apreciar como la mayor parte de los componentes se encuentra cercana a la «Secuencia principal». Algunos de ellos están a más de una desviación estándar (Z=1) de la media. Merece la pena revisar estos componentes ya que o son muy abstractos con pocas dependencias o son muy concretos con muchas dependencias.

Otra manera de utilizar la métrica D es ver como evoluciona este en el tiempo. Por ejemplo, si tenemos un componente Payroll se puede apreciar como en el siguiente gráfico hay algunas dependendencias que han estado creciendo alrededor del componente sobre las últimas fáses de release. 



El gráfico muestra una línea de control en D = 0.1. El punto R2.1 ha excedido este límite de control, así que merece la pena encontrar el porqué este componente está tan lejos de la secuencia principal.

Conclusión

Las métricas de administración de dependencias descritas miden la conformidad de un buen diseño para un patrón de dependencia y abstracción, y este patrón es un buen patrón. 

La experiencia demuestra que ciertas dependencias son buenas y otras son malas. Este patrón refleja esa experienia. Sin embargo, una métrica no es algo ley ferrea y, de hecho, están lejos de ser perfectas pero son unas directrices que son útiles.

No hay comentarios:

Publicar un comentario