Diseño descendente
La estructura de componentes no se diseña de manera descendente si no que esta
evoluciona a medida que se desarrolla es sistema.
La estructura de dependencia de componentes no tiene que ver con la funcionalidad
de la aplicación. Esta tiene que ver con la construibilidad y la mantenibilidad
del sistema. Esta es la razón por la cual no se diseña al principio del
proyecto. No hay nada que construir ni nada que mantener.
A medida que el sistema se va desarrollando se necesita gestionar las dependencias que
van surgiendo. Se deberían usar «Single Responsibility Principle» y «Common
Closure Principle» para agrupar las clases que cambian juntas.
Una de las principales preocupaciones de la estructura de dependencias es aislar la
volatilidad. Los componentes no deberían cambiar frecuentemente y deberían ser
estables. En este punto,el gráfico de dependencia se utiliza para proteger los
componentes estables frente a los componentes volátiles.
Cuando el sistema sigue creciendo surge la necesidad de la reusabilidad. En este punto el
«Common Reuse Principle» comienza a influir en la estructura de los componentes.
Como se puede observar la estructura de dependencia de componentes se va desarrollando
a medida que el sistema crece.
El Principio de dependencias estables
El diseño no puede ser completamente estático dado que es necesario algo de volatilidad
si hay que mantener el diseño. Por el «Common Closure Principle» se crean
componentes que son sensibles a ciertos tipos de cambios pero inmunes a otros.
Algunos de estos componentes están diseñados para ser volátiles. Se espera que
ellos cambien.
Ningún componente que se espera que sea volátil debería depender de un componente que
es difícil de cambiar. De otra manera, el componente volátil también sería
complicado de cambiar.
Esta es la perversidad del software dado que un módulo que has diseñado para que sea fácil
de cambiar se convierta en difícil de cambiar por alguien quién simplemente
cuelga una dependencia con él. No se ha cambiado una sóla línea de código en el
módulo pero debido a la dependencia este es más difícil de cambiar. Al cumplir
con el «Stable Dependency Principle» nos aseguramos de que los módulos que son
fáciles de modificar no dependen de módulos que sean más difíciles de cambiar.
Estabilidad
Lo primero sería definir qué es la estabilidad. Si se pone de canto una moneda tenemos la
sensación de que no está en una posición estable. No obstante, si la moneda no
sufre ninguna perturbación podría estar un tiempo indefinido en esa posición.
Podemos concluir que la estabilidad no tiene que ver con la frecuencia de
cambio.
Una definición más acertada sería que la estabilidad tiene que ver con la cantidad
de trabajo que se requiere para producir un cambio. En el caso de la moneda, no
se requiere mucha cantidad de trabajo para que cambie su estado y por ello se
considera inestable.
La estabilidad de un componente software va a depender de muchos factores como
pueden ser su tamaño, la complejidad que albergue, su claridad, etc. Una manera
de hacer un componente difícil de cambiar es hacer que otros componentes
dependan de este componente. En este caso, cualquier cambio en el componente
requiere cambios en todos los componentes dependientes.
En el siguiente diagrama se puede observar 4 componentes. El componente X es un
componente del cual dependen los otros 3. Se dice que el componente X es
estable debido a que tiene 3 razones para no cambiar. No obstante, el
componente X no tiene dependencias por lo que se dice que este es independiente.
Métricas de estabilidad
¿Cómo se puede medir la estabilidad de un componente? Una forma es contar el número de
dependencias que entran y salen de ese componente. Estos número nos indicarán
la estabilidad posicional del componente.
· Fan-in: dependencias de entrada. Estas métricas identifican el número de
clases fuera del componente que dependen de clases de dentro del componente.
· Fan-out: dependencias de salida.
· I: Instability: «I = Fan-out / (Fan-in + Fan-out)». Esta métrica
tiene el rango [0,1]. I con el valor 0 indica un valor estabilidad máxima
mientras que I = 1 tiene una inestabilidad máxima.
Las métricas «Fan-out» y el «Fan-in» se calculan contando el número de clases fuera
del componente que tiene dependencia con las clases dentro del componente en
cuestión.
Considerando el siguiente diagrama se va a proceder a calcular a la estabilidad del
componente «Cc».
Se puede apreciar que hay 3 clases fuera del componente «Cc» que dependen de clases del
componente «Cc». Entonces, el «Fan-in» es 3. Además, hay una clase «v»
del componente «Cd» que es dependiente de la clase «u» del componente «Cc». Por lo tanto el «Fan-out» es 1 y la Inestabilidad «I» tiene un valor:
Cuando la métrica «I» es igual a 1 quiere decir que ningún otro componente depende de
este componente (Fan-in = 0) y este componente depende de otros (Fan-out >
0).
En el siguiente diagrama se puede apreciar como el Componente A tiene un «Fan-in» de
0 y un «Fan-out» de 3 dando una estabilidad de 1. Esta situación representa la
máxima inestabilidad de un componente. Este componente es dependiente e
irresponsable.
Cuando la métrica «I» es igual a 0 significa que otros componentes depende de él
(«Fan-out» > 0) pero él mismo no depende de otros componentes («Fan-In» =
0). Este es un componente tan estable como puede llegar a ser.
En el siguiente diagrama se puede apreciar como el Componente D tiene un «Fan-in» de
3 y u «Fan-out» de 0 dando lugar a una estabilidad de 0. Esta situación
representa todo lo estable que un componente puede llegar a ser.
Sus dependencias hacen más complicado cambiar el componente y no tiene dependencias
que lo obliguen a cambiar.
El «Stable Dependency Principle» establece que la métrica «I» de un componente debería ser
mayor que la métrica «I» de los componentes que este depende. Esto significa
que las métricas «I» deberían disminuir en la dirección de la dependencia.

No todos los componentes deberían ser estables
Si todos los componentes de un sistema tuvieran la máxima estabilidad el sistema no
sería capaz de cambiar y esto no es una situación deseable. Una buena
arquitectura debe tener una arquitectura de componentes de manera que algunos
componentes son estables y otros inestables.
Imaginemos un sistema que inicialmente está formado por tres componentes.
A partir de este punto se requiere de un nuevo componente «Cd» y este se diseña de manera
que sea fácil de cambiar, es decir, que sea volátil. Una vez creado y añadido
al sistema, un desarrollador crea una dependencia de una de las clases del
componente «Cc» (estable) al componente «Cd» (volátil) quedando de la siguiente
manera.
Esto cambia las métricas por lo que hace que el componente volátil, que inicialmente se
diseñó para ser fácil de cambiar, sea difícil de cambiar ya que un cambio en
este forzará a tratar con todas las dependencias que tenga el componente
estable.
La única manera de volver a hacer que el componente volátil sea fácil de cambiar es que
este no tenga dependencia con el componente estable. Imaginemos que el
componente estable tiene una clase A de la cual hace uso una clase B que es
parte del componente volátil.
Para solucionar este problema se puede recurrir al «Dependency Inversion Principle».
En este caso se puede crear una interfaz «AI» e incluir esta en un nuevo
componente «AServer». Esta nueva interfaz debe debe definir todos los métodos
que la clase A necesita usar. Entonces, se hace que la clase B implemente esta
interfaz tal y como se muestre en la siguiente imagen.
Esto rompe la dependencia del componente estable con el componente volátil. Ahora, ambos
componentes dependen del componente «AServer». El componente «AServer» es un
componente muy estable dado que su métrica «I» tiene un valor de 0 mientras que
el componente volátil mantiene su inestabilidad máxima con un valor de «I» de 1
(I=1/1=1).
Ahora se puede decir que no se vulnera el «Stable Dependency Principle» y que todas las
dependencias fluyen ahora en dirección de «I» decreciente.
Componentes abstractos
Es posible encontrarse con un componente que sólo tenga una interfaz y nada de código
ejecutable como puede ser el caso de «Aserver». Esto son componentes abstractos
con la máxima estabilidad que hace que otros componentes menos estables
dependan de ellos.
No hay comentarios:
Publicar un comentario