Cada vez que creas un objeto dentro de una función, la función depende de la clase de ese objeto. En otras palabras, la función está firmemente acoplada a una clase específica. Hay una manera de verificar cuán enredado está tu código: toma cualquier función e imagina que la trasladas a otro proyecto. ¿Cuántas dependencias arrastrará consigo? Si trasladar la función requiere mover mucho código, significa que tu código tiene un alto acoplamiento.
Para desacoplar el código, hay un término especial llamado Principio de Inversión de Dependencias. También se conoce como DIP dentro de SOLID. Aquí está su formulación:
- Los módulos de nivel superior no deben depender de los módulos de nivel inferior. Ambos tipos de módulos deben depender de abstracciones.
- Las abstracciones no deben depender de los detalles. Los detalles deben depender de las abstracciones.
Dependiendo del lenguaje, estas frases pueden tener un significado ligeramente diferente. En general, dicen que no debes acoplarte a una implementación específica de una clase. Crear objetos en el lugar donde se utilizan nos vincula con la clase de esos objetos sin posibilidad de sustituirlos. El enfoque correcto, según este principio, es invertir las dependencias, es decir, no trabajar directamente con clases, sino obtener los objetos necesarios desde fuera, por ejemplo, a través de los parámetros de la función.
Además, DIP recomienda acoplarse a interfaces en lugar de clases en las firmas de las funciones. Hablaremos de esto más adelante, cuando terminemos con los conceptos básicos.
Era:
const doSomething = () => {
const logger = new Logger();
// some code
};
Ahora es:
const doSomething = (logger) => {
// some code
};
En las charlas sobre DIP, a los ponentes les gusta usar la analogía del principio de Hollywood: "No nos llames, nosotros te llamaremos". Esto significa que no debes usar clases directamente, sino obtener objetos preparados como una dependencia externa.
¿Es necesario seguir siempre este principio? Sinceramente, el código completamente construido de esta manera se vuelve excesivamente abstracto y difícil de entender. En programación no hay soluciones mágicas y en cada situación concreta hay que considerar las condiciones y la tarea a resolver. Si se necesita sustituir una implementación, lo hacemos; si no, trabajamos directamente.
Casi siempre, cuando se habla de inversión de dependencias, aparece el término "inyección de dependencias". DIP se refiere a la modularidad, y la inyección de dependencias se refiere a las formas en que se puede lograr esa modularidad, cómo pasar dependencias al código. Hay tres formas de inyección de dependencias:
Pasarlas como argumentos de funciones o métodos. Hasta ahora hemos utilizado este enfoque:
doSomethingUseful(new Logger());A través del constructor en situaciones donde se utilizan objetos:
const app = new Application(new Logger());A través de setters. Si es posible, es mejor no utilizar este método, ya que implica modificar objetos y puede afectar la integridad:
const app = new Application(); app.setLogger(new Logger());
Como puedes ver, detrás de un término complicado se esconde algo muy simple: pasar parámetros. Por otro lado, los términos permiten entender más sin necesidad de conocer el contexto adicional. Lo importante es no exagerar, ya que podrías convertirte en un astronauta de la arquitectura.
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.