Curso de Node.js Avanzado

Decorators e inyección de dependencias en Node.js

Curso de Node.js Avanzado

Contenido del curso

Decorators e inyección de dependencias en Node.js

Resumen

Los decorators y la inyección de dependencias son dos patrones que, combinados, te permiten extender la funcionalidad de tus clases en Node.js sin modificar su código original. Aprenderás cómo aplicarlos con un ejemplo práctico de un servicio de datos al que le añadiremos logging dinámico, una técnica útil para cualquier desarrollador backend.

Qué son los decorators y por qué importan en Node.js

Un decorator es un patrón de diseño que envuelve un objeto o clase para agregarle nuevas capacidades sin tocar su implementación original. En el ecosistema de Node, este patrón ganó popularidad gracias a Fastify, un framework que lo usa para extender objetos como el request o el response durante el ciclo de vida de una petición [0:15].

La idea central es simple: encapsulas el objeto que quieres decorar dentro de otra clase y reutilizas su lógica añadiendo comportamiento extra. Así puedes mantener limpio el código base y sumar funcionalidades como logs, métricas o validaciones cuando las necesites.

¿Qué hace un decorator en programación? Toma un objeto existente y le añade comportamiento adicional sin modificar su código original. Lo envuelve dentro de otra clase que reutiliza su lógica.

Cómo funciona la inyección de dependencias en JavaScript

La inyección de dependencias es otro patrón clave, muy presente en frameworks como Next.js de Vercel, donde los providers de seguridad son dependencias que se inyectan en la aplicación [0:48]. La gracia está en que tu clase no crea sus dependencias internamente, sino que las recibe desde afuera, normalmente por el constructor.

Esto te da flexibilidad enorme. Puedes intercambiar implementaciones sin reescribir la clase que las consume, siempre que cumplan con la interfaz esperada.

Por qué combinar decorators con inyección de dependencias

Juntos, ambos patrones se vuelven poderosos. El decorator extiende la funcionalidad y la inyección permite que esa extensión sea configurable. Imagina decorar un servicio con un logger que hoy escribe en consola y mañana en un archivo, sin tocar la lógica del servicio.

Cómo crear un decorator paso a paso con un DataService

Empezamos creando una carpeta llamada decorators-DI y dentro un archivo index.js. La primera clase es DataService, con un único método processData que recibe un array y multiplica cada elemento por dos [2:30].

javascript class DataService { processData(data) { return data.map(item => item * 2); } }

La operación en sí no importa demasiado. Lo relevante es que tenemos una funcionalidad sencilla lista para ser decorada.

Cómo decorar una clase con logging en Node.js

Ahora viene la parte interesante: creamos DataServiceWithLogging, una clase que recibe en su constructor tanto el dataService original como un logger inyectado [3:40].

javascript class DataServiceWithLogging { constructor(dataService, logger) { this.dataService = dataService; this.logger = logger; }

processData(data) { this.logger.log("iniciando procesamiento"); const resultado = this.dataService.processData(data); this.logger.log("finalizando procesamiento"); return resultado; } }

Fíjate en el patrón: encapsulamos la función original, la ejecutamos en medio del flujo y añadimos logs antes y después. La lógica base sigue intacta.

Cómo definir un logger reutilizable como dependencia

El logger puede ser cualquier objeto que tenga un método log. Esa es la única condición que la clase decoradora exige.

javascript class Logger { log(message) { console.log([Logger]: ${message}); } }

Mañana podrías cambiarlo por uno que escriba en archivo, en una base de datos o en un servicio remoto. A DataServiceWithLogging no le importa mientras la función log exista y se pueda ejecutar [7:55].

¿Qué es la inyección de dependencias? Es un patrón donde una clase recibe sus dependencias desde afuera en lugar de crearlas internamente. Permite intercambiar implementaciones sin modificar la clase consumidora.

Cómo ejecutar el servicio decorado

Con todo definido, instanciamos los objetos y los conectamos. Primero el servicio base, luego el logger y finalmente el servicio decorado que combina ambos:

javascript const baseService = new DataService(); const logger = new Logger(); const decoratedService = new DataServiceWithLogging(baseService, logger);

const inputData = [1, 2, 3, 4]; const processedData = decoratedService.processData(inputData); console.log("Resultado procesado:", processedData);

Al ejecutar el código, verás los logs de inicio y fin del procesamiento, además del resultado final con los números multiplicados por dos. La clase original nunca supo que estaba siendo decorada, y ese es exactamente el punto.

¿Cuál es la diferencia entre decorator e inyección de dependencias? El decorator envuelve un objeto para extender su comportamiento. La inyección de dependencias entrega objetos a una clase desde afuera. Combinados, te permiten extender funcionalidad de forma flexible y configurable.

Qué patrones quedan listos para tu próximo proyecto

Con este ejercicio practicaste tres habilidades concretas: encapsular clases dentro de decoradores, inyectar dependencias por constructor y diseñar contratos mínimos basados en métodos esperados, no en clases concretas. Esto último es la base del principio de inversión de dependencias y abre la puerta a código mucho más testeable.

Si vas a llevarlo a producción, piensa en loggers especializados, decoradores que midan tiempos de ejecución o capas que validen inputs antes de delegar al servicio base. ¿Qué otra funcionalidad le añadirías a tu DataService con un decorator? Cuéntame en los comentarios.