Habilidad de desarrollo
independiente
Cuando los componentes
están fuertemente desacoplados, se mitiga la interferencia entre los equipos.
Si las reglas de negocio no conocen la UI, entonces un equipo que se enfoca en
la UI no puede afectar mucho a un equipo que se enfoca en las reglas de
negocio.Si los propios casos de uso están desacoplados entre sí, es poco
probable que un equipo que se centre en el caso de uso de crear un pedido se
enfoque en el caso de uso de borrar un pedido.
Siempre que las capas y
los casos de uso se desacoplen, la arquitectura del sistema apoyará la
organización de los equipos, independientemente de si están organizados como
equipos de características, equipos de componentes, equipos de capas o alguna
otra variación.
Despliegue independiente
El desacoplamiento de
los casos de uso y las capas también ofrece un alto grado de flexibilidad en la
implementación.De hecho, si el desacoplamiento se realiza bien, entonces
debería ser posible cambiar capas y casos de uso en sistemas en ejecución.
Agregar un nuevo caso de uso podría ser tan simple como agregar algunos nuevos
archivos jar o servicios al sistema y dejar el resto solo.
Duplicación
Los arquitectos a menudo
caen en una trampa, una trampa que depende de su miedo a la duplicación.
La duplicación es
generalmente una mala cosa en el software. No nos gusta el código duplicado.
Cuando el código está realmente duplicado, estamos obligados como profesionales
a reducirlo y eliminarlo.
Pero hay diferentes
tipos de duplicación. Hay una verdadera duplicación, en la que cada cambio en
una instancia requiere el mismo cambio en cada duplicado de esa instancia.
Entonces hay duplicación falsa o accidental, si dos secciones del código
aparentemente duplicadas evolucionan a lo largo de diferentes caminos, si
cambian a diferentes velocidades y por diferentes razones, entonces no son
verdaderos duplicados. Si volvemos a ellos en unos años se verá que son muy
diferentes entre sí.
Ahora imagine dos casos
de uso que tienen estructuras de pantalla muy similares. Los arquitectos
probablemente estarán tentados a compartir el código para esa estructura. Pero
deberían hacerlo? ¿Es eso una verdadera duplicación? ¿O es accidental?
Lo más probable es que
sea accidental. A medida que pasa el tiempo, lo más probable es que esas dos
pantallas divergan y eventualmente se vean muy diferentes. Por este motivo, se
debe tener cuidado para evitar su unificación. De lo contrario, separarlos más
tarde será todo un desafío.
Cuando esté separando
verticalmente los casos de uso entre sí, se encontrará con este problema, y
su tentación será unir los casos de uso porque tienen estructuras de pantalla
similares, algoritmos similares, consultas de bases de datos y / o esquemas
similares. Resista la tentación de cometer el pecado de la eliminación
automática de la duplicación. Asegúrese de que la duplicación es real.
De la misma manera,
cuando se están separando las capas horizontalmente, es posible que observe que
la estructura de datos de un registro de base de datos particular es muy
similar a la de los datos. Se puede tener la tentación de simplemente pasar el
registro de la base de datos hast ala interfaz de usuario, en lugar de crear un
modelo vista que se vea igual y copie los elementos. Hay que tener cuidado:
esta duplicación es casi seguramente accidental. Crear el modelo de vista
separado no es un gran esfuerzo, y ayudará a mantener las capas desacopladas
correctamente.
Desacoplando modos (de
nuevo)
De vuelta a los modos.
Hay muchas formas de desacoplar capas y casos de uso. Se pueden desacoplar en
el nivel del código fuente, en el nivel del código binario (implementación) y
en el nivel de la unidad de ejecución (servicio).
Nivel de código
Podemos controlar las
dependencias entre los módulos de código fuente para que los cambios en un
módulo no obliguen a los cambios o la compilación de otros (por ejemplo, Ruby
Gems).
En este modo de
desacoplamiento, todos los componentes se ejecutan en el mismo espacio de
direcciones y se comunican entre sí mediante llamadas de función simple. Hay un
solo ejecutable cargado en la memoria de la computadora. Popularmente se conoce
como una estructura monolítica.
Nivel de despliegue
Podemos controlar las
dependencias entre unidades desplegables, como archivos jar, DLL o bibliotecas
compartidas, para que los cambios en el código fuente en un módulo no obliguen
a otros a reconstruirse y volver a implementarse.
Muchos de los
componentes aún pueden vivir en el mismo espacio de direcciones y comunicarse a
través de llamadas de función. Otros componentes pueden vivir en otros procesos
en el mismo procesador y comunicarse a través de comunicaciones entre procesos,
sockets o memoria compartida. Lo importante aquí es que los componentes
desacoplados se dividen en unidades de implementación independiente, como
archivos jar, archivos Gem o DLL.
Nivel de servicio
Podemos reducir las
dependencias hasta el nivel de las estructuras de datos y comunicarnos
únicamente a través de paquetes de red, de modo que cada unidad de ejecución
sea totalmente independiente de los cambios de fuente y binarios a otros (por
ejemplo, servicios o microservicios).
¿Cuál es el mejor modo
para usar?
La respuesta es que es
difícil saber qué modo es el mejor durante las fases iniciales de un proyecto.
De hecho, a medida que el proyecto madura, el modo óptimo puede cambiar.
Por ejemplo, no es
difícil imaginar que un sistema que se ejecute cómodamente en un servidor en
este momento pueda crecer hasta el punto en que algunos de sus componentes
deban ejecutarse en servidores separados. Mientras que el sistema se ejecuta en
un solo servidor, el desacoplamiento a nivel de origen podría ser suficiente.
SIn embargo, más tarde, podría requerir el desacoplamiento en unidades
desplegables o incluso servicios.
Una solución (que parece
ser popular en este momento) es simplemente desacoplar en el nivel de servicio
de forma predeterminada. Un problema con este enfoque es que es caro y alienta
el desacoplamiento de grano grueso. No importa cuán “micro” sean los
microservicios, es probable que el desacoplamiento no sea lo suficientemente
detallado.
Otro problema con el
desacoplamiento a nivel de servicio es que es costoso, tanto en tiempo de
desarrollo como en recursos del sistema. Tratar con los límites del servicio
donde no se necesitan es un desperdicio de esfuerzo, memoria y ciclos. Y, sí,
sé que los dos últimos son baratos, pero el esfuerzo no lo es.
Se recomienda empujar el
desacoplamiento hasta el punto donde se podría formar un servicio, si
fuera necesario, pero luego dejar los componentes en el mismo espacio de
direcciones el mayor tiempo posible. Esto deja abierta la opción para un
servicio.
Con este enfoque,
inicialmente los componentes se separan en el nivel del código fuente. Eso
puede ser lo suficientemente bueno para la duración del proyecto. Sin embargo,
si surgen problemas de implementación o desarrollo, puede ser suficiente llevar
un poco de desacoplamiento a un nivel de implementación, al menos por un
tiempo.
A medida que aumentan
los problemas de desarrollo, implementación y operación, se elije
cuidadosamente qué unidades desplegables se convertirán en servicios y
gradualmente cambiaré el sistema en esa dirección.
Con el tiempo, las
necesidades operativas del sistema pueden disminuir. Lo que una vez requirió
desacoplamiento en el nivel de servicio ahora puede requerir solo desacoplamiento
a nivel de implementación o incluso a nivel de fuente.
Una buena arquitectura
permitirá que un sistema nazca como un monolito, implementado en un solo
archivo, pero luego se convierta en un conjunto de unidades desplegables
independientemente, y luego a servicios independientes y / o microservicios.
Más tarde, a medida que cambian las cosas, debería permitir revertir esa
progresión y deslizarse hacia abajo en un monolito.
Una buena arquitectura
protege a la mayoría del código fuente de esos cambios. Deja el modo de
desacoplamiento abierto como una opción para que las implementaciones grandes
puedan usar un modo, mientras que pequeños despliegues pueden usar otro.
Conclusión
Sí, esto es complicado.
Y no estoy diciendo que el cambio de los modos de desacoplamiento deba ser una
opción de configuración trivial (aunque a veces eso es apropiado). Lo que estoy
diciendo es que el modo de desacoplamiento de un sistema es una de esas cosas
que probablemente cambiará con el tiempo, y un buen arquitecto prevé y facilita
apropiadamente esos cambios.
No hay comentarios:
Publicar un comentario