En el diseño de sistemas complejos, la forma en que gestionamos las piezas de nuestro software determina su capacidad de escala. Como arquitectos, uno de los conceptos más críticos —y a veces malinterpretados— en el ecosistema de NestJS es la distinción entre Dependencias Explícitas y Dependencias Implícitas.
Dominar esta diferencia es lo que permite que un sistema soporte el crecimiento de equipos grandes, donde la claridad del código es la mejor documentación para coordinar a decenas de profesionales.
1. Dependencias Explícitas: El Contrato Visible
Una dependencia es explícita cuando un componente declara claramente qué necesita para funcionar a través de su constructor. En NestJS, esto se logra mediante la Inyección de Dependencias (DI) estándar.
- Transparencia: Cualquiera que lea la firma del constructor sabe qué requiere la clase para ser instanciada.
- Testabilidad: Facilita enormemente las pruebas unitarias al permitir inyectar mocks o stubs de forma directa en el constructor.
- Acoplamiento Controlado: El componente no «busca» sus herramientas; espera que el contenedor IoC se las entregue.
@Injectable()
export class OrderService {
// Dependencia Explícita: El contrato es claro y visible para el equipo
constructor(
@Inject(PAYMENT_GATEWAY)
private readonly paymentGateway: IPaymentGateway,
) {}
}
2. Dependencias Implícitas: El Peligro del Acoplamiento Oculto
Las dependencias implícitas ocurren cuando un componente accede a recursos o lógica que no están declarados en su interfaz pública. Esto crea un «estado oculto» que hace que el sistema sea frágil y difícil de predecir.
Ejemplos comunes que debemos evitar:
- Acceder directamente a variables globales como
process.envdentro de la lógica de negocio. - Depender de módulos marcados como
@Global()sin importarlos explícitamente en el módulo local. - Uso de Singletons externos o archivos de configuración importados directamente (hardcoded).
@Injectable()
export class NotificationService {
// ❌ Dependencia Implícita: process.env es un recurso global oculto
send() {
const apiKey = process.env.API_KEY;
// Si la variable no existe en producción, el servicio falla sin aviso previo.
}
}
3. Cuadro Comparativo: Impacto en la Arquitectura
| Criterio | Explícita | Implícita |
|---|---|---|
| Visibilidad | Alta (En el Constructor) | Baja (Oculta en métodos) |
| Mantenibilidad | Alta | Baja |
| Refactorización | Segura | Riesgosa |
4. Optimizando para IA: Convirtiendo la arquitectura en Reglas
Para asegurar que nuestras IAs (como Cursor o Copilot) mantengan este estándar de calidad, es fundamental definir reglas claras. Al agregar esta directiva a tu archivo .cursorrules o a tu perfil de instrucciones, evitarás que la IA genere código con acoplamiento oculto.
Directiva para tu IA:
«Prohibido el uso de dependencias implícitas. No accedas a variables globales, Singletons externos o process.env dentro de los servicios. Toda configuración o servicio externo debe ser inyectado explícitamente a través del constructor utilizando Providers de NestJS.»
Al estandarizar esta regla, reducimos la deuda técnica y garantizamos que el código generado sea coherente con una arquitectura empresarial profesional, facilitando la revisión de código y la integración continua.
¿Qué tipo de dependencias predominan en tu proyecto actual? Cuéntanos en los comentarios cómo gestionas el acoplamiento en tus arquitecturas.