Arquitectura Invisible: El Peligro de las Dependencias Implícitas en NestJS

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.env dentro 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

CriterioExplícitaImplícita
VisibilidadAlta (En el Constructor)Baja (Oculta en métodos)
MantenibilidadAltaBaja
RefactorizaciónSeguraRiesgosa

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.

Leave a Comment