Este artículo es sobre el segundo grupo de conceptos de los que quería hablar después de releer Clean Architecture.
Quiero intentar algo diferente esta vez: En lugar de elaborar cada idea en prosa larga y continua, las enumeraré como fragmentos separados.
Así que, aquí va:
- Ya sabemos que el acoplamiento estrecho es algo malo. Une el software de una manera que lo hace difícil de cambiar y adaptar a cambios futuros. Si dos piezas de software están estrechamente acopladas, no pueden cambiar independientemente y el mantenimiento se vuelve más difícil como resultado.
- En un escenario ideal, la mayoría de tu código debería depender de abstracciones en lugar de depender de clases/construcciones de software concretas. En lenguajes OOP de tipado estático, esto significa que la mayoría de las referencias deberían ser a interfaces o clases abstractas y que DI se usa para controlar el flujo de dependencias. Para lenguajes de tipado dinámico puedes lograr prácticamente lo mismo con duck typing.
- Los ciclos de dependencias suceden cuando una clase depende de una clase que depende de … que depende de la primera clase de la cadena. Estas son algunas de las cosas más molestas de tratar en un proyecto, pero pueden ser resueltas (en la mayoría de casos) usando el Principio de Inversión de Dependencias.
- Una forma común de depender de cosas concretas es cuando atas tu proyecto a tecnologías/librerías específicas. Como llamar directamente métodos de la librería cliente de alguna base de datos a través de todo tu código (o peor, esparcir SQL por todas partes). En su lugar, deberías esconder esos detalles detrás de una interfaz claramente definida adaptada al problema que estás tratando de resolver, hará las cosas más fáciles si necesitas cambiar tecnología en el futuro.
- La razón real para depender de abstracciones es que los conceptos de alto nivel tienden a cambiar menos frecuentemente que los detalles de implementación. Si defines un conjunto coherente de comportamiento en una interfaz, es poco probable que cambie tan a menudo como las clases que la implementan. Se trata de que son construcciones de software mucho más estables.
- Es imposible tener un sistema con solo componentes estables. La estabilidad está atada a los requerimientos, y si cambian tu sistema necesitará cambiar también. Lo único que puedes hacer es asegurar que los componentes que encarnan esa inestabilidad no sean directamente referenciados y estén escondidos detrás de interfaces/abstracciones limpias.
- Hablando de “concreciones”, puedes medir que tan “sucio” es un componente revisando qué tan dependiente es de detalles de implementación. El método main muy a menudo será la parte más sucia de tu sistema. Esto está bien, si alguna parte de tu sistema puede permitirse atracones de dependencias y acoplamiento estrecho, ese es el método main.
- Otro beneficio de no atar tu sistema a implementaciones/tecnologías concretas es que se vuelve más fácil removerlas o cambiarlas totalmente en el futuro. Esconderlas detrás de una interfaz te permite delegar esas elecciones al tú del futuro. La contraparte de ti que vive en el futuro tiene mucho más conocimiento sobre las necesidades del sistema y está mejor equipado para hacer esas elecciones, así que hazle fácil a tu compañero implementar esas decisiones.
Esas son las que puedo recordar, todas encarnan exactamente la misma idea: Construye tu sistema de una manera que proteja tu lógica de negocio de conocer detalles de implementación.
Hoy en día tenemos una enorme gama de lenguajes increíbles que hacen esto extremadamente fácil, ¡así que usa esas características para construir gran software!
También, si estás interesado en principios de diseño para lograr esto, puedes echar un vistazo a una serie de artículos que escribí sobre los principios S.O.L.I.D, espero que los encuentres útiles.
Gracias por leer.