Principio de Responsabilidad Única en NestJS: Creación de Controladores

Clase 10 de 24Curso de Backend con NestJS

Contenido del curso

REST API

Integridad de datos

Resumen

Escribir código limpio y fácil de mantener comienza por aplicar principios sólidos de arquitectura. El principio de responsabilidad única (Single Responsibility Principle), parte de los patrones SOLID, establece que cada método y cada clase deben ocuparse de una sola tarea. Aplicar este concepto en NestJS transforma la forma en que organizas tus controladores y te prepara para escribir pruebas unitarias más efectivas.

¿Qué significa que un método tenga una sola responsabilidad?

La idea es directa: si un método se llama suma, solo debería sumar [0:09]. Si dentro de ese mismo método estás dividiendo o restando, estás violando el principio. Cada método debe hacer una única cosa y hacerla bien. Esto no solo mejora la legibilidad del código, sino que facilita la creación de pruebas unitarias y end to end.

Este mismo razonamiento se extiende a las clases. Cuando un controlador atiende endpoints de products, categories y filter al mismo tiempo, está acumulando responsabilidades diferentes [1:00]. Si el API crece, ese controlador se vuelve enorme y difícil de mantener.

¿Cómo se aplica este principio a los controladores de NestJS?

La solución es crear un controlador por cada recurso. En lugar de tener un solo controller con todos los endpoints, se separan en:

  • Un controlador dedicado exclusivamente a products.
  • Un controlador dedicado exclusivamente a categories.
  • Métodos específicos dentro de cada controlador, cada uno con su única responsabilidad.

De esta manera, si necesitas modificar la lógica de categorías, sabes exactamente dónde buscar sin recorrer un archivo interminable.

¿Cómo generar controladores desde el CLI de NestJS?

El CLI de NestJS ofrece comandos para crear artefactos como clases, controladores, decoradores y filtros directamente desde la terminal [2:07]. Para generar un controlador se utiliza el comando:

bash nest generate controller products

O con la abreviatura:

bash nest g controller products

Este comando produce dos archivos: el controlador y un archivo de pruebas unitarias [2:40]. Además, actualiza automáticamente el app.module.ts registrando el nuevo controlador en la sección de controllers.

¿Cómo organizar los controladores en carpetas?

Por defecto, el CLI crea una subcarpeta con el nombre del recurso. Si prefieres una estructura más plana y visual, puedes usar la bandera --flat [3:30]:

bash nest g controller controllers/products --flat

Esto coloca el archivo directamente dentro de la carpeta controllers sin crear subcarpetas adicionales. Para categorías, el proceso es idéntico:

bash nest g controller controllers/categories --flat

El resultado es una carpeta controllers con todos los controladores organizados de forma lineal [4:12]. El app.module.ts queda actualizado automáticamente con las referencias a ProductsController y CategoriesController.

¿Qué ventaja tiene definir la ruta en el decorador del controlador?

Cuando el CLI genera un controlador como ProductsController, incluye el nombre del recurso en el decorador @Controller('products') [5:24]. Esto significa que no necesitas repetir /products en cada endpoint. Todos los métodos dentro de ese controlador heredan la ruta base.

Por ejemplo, si antes tenías:

typescript @Get('products/filter')

Ahora solo necesitas:

typescript @Get('filter')

El framework se encarga de componer la ruta completa: /products/filter. Lo mismo aplica para categories: cualquier método bajo CategoriesController parte de /categories como ruta base [5:50].

Una vez realizada la migración, los endpoints funcionan exactamente igual que antes. La diferencia está en la organización interna: cada controlador gestiona únicamente los endpoints de su recurso, y las rutas quedan más limpias al no repetir el path del recurso en cada método.

¿Qué importaciones necesitas en cada controlador?

Al mover los métodos, debes asegurarte de importar los decoradores correspondientes desde @nestjs/common [5:05]:

  • @Get para métodos de lectura.
  • @Param para recibir parámetros de ruta.
  • @Query para recibir query params.

Con esto, cada controlador queda autónomo y con sus dependencias claramente definidas.

Ahora que conoces cómo separar responsabilidades y generar controladores desde el CLI, el reto es crear los endpoints para orders, users, customers y brands [7:04]. Practica clasificándolos en controladores independientes, configurando rutas y jugando con parámetros. Comparte cómo te quedó el resultado.