← Arquitectura por capas con Spring

Sesión 18 · Semana 9

Consolidar las capas del mismo proyecto

Proyecto compartido. En el taller de Intermodular que abre esta semana has trabajado comprobar el contrato publicado. En Servidor continúas la implementación del mismo producto.

Se explica

25 minutos · explicación y demostración

Ya dispones de capas, inyección y pruebas de reglas. Hoy revisarás que toda la API aplica esa separación antes de sustituir la memoria por PostgreSQL. La colección verifica el contrato HTTP y los tests del servicio verifican las decisiones internas: necesitas ambas comprobaciones.

Terminar es tachar

Una refactorización a medias es peor que no haberla empezado: deja dos formas de hacer lo mismo conviviendo, y quien llegue después no sabrá cuál es la buena.

Abre el análisis de problemas. Para cada línea, una de tres:

Qué hacer con cada problema apuntado
  1. Resuelto: táchalo y escribe en qué clase vive ahora eso
  2. Sigue vivo: resuélvelo hoy
  3. Ya no aplica: explica por qué dejó de ser un problema

No vale dejar líneas sin marcar. Ese documento es la justificación de la unidad y hoy es su comprobación.

Comprobar una refactorización completa

Refactorizar cambia cómo se organiza el código manteniendo el comportamiento acordado. Si la colección que pasaba antes deja de pasar, no basta con que las carpetas se llamen controller, service y repository: hay una regresión que localizar. La primera evidencia es la comparación del mismo recorrido antes y después.

El controlador interpreta HTTP y construye respuestas; el servicio ejecuta el caso de uso y sus reglas; el repositorio ofrece acceso a los datos. Para comprobar la separación, sigue una operación de escritura y pregunta quién decide si es válida, quién guarda y quién elige el estado HTTP. Una regla repetida en dos controladores debe tener un lugar común en el servicio.

Las pruebas de servicio completan la colección HTTP: permiten provocar un conflicto de negocio sin arrancar el servidor y comprobar que no se guarda un dato inválido. La revisión de hoy conecta ambas evidencias con el código. La arquitectura está terminada cuando es comprensible, comprobable y conserva el contrato; contar paquetes o anotaciones no demuestra esas propiedades.

Se trabaja

140 minutos · implementación guiada sobre el proyecto propio

Paso 1 · Retomar el proyecto y preparar la comprobación

  1. Abre el árbol de paquetes, los tests del servicio y la colección. Ejecuta ambos recorridos antes de corregir la arquitectura.
  2. Elige una regla y localiza su única implementación. Anota si se repite en otro controlador o depende indebidamente de HTTP.
  3. Selecciona otra entidad de tu dominio y comprueba qué capas o tests le faltan para alcanzar la misma estructura.

Paso 2 · Especificación · el estado final

Estructura del proyecto

com.ejemplo.gestor
├── controller     · habla HTTP y nada más
├── dto            · lo que se acepta y lo que se publica
├── mapper         · traduce entre DTO y modelo
├── service        · casos de uso y reglas de negocio
├── repository     · interfaces, con su implementación en memoria
├── model          · lo que maneja tu código
├── validacion     · anotaciones propias
└── error          · excepciones, formato y manejador

Reglas que se comprueban

# Criterio Cómo se verifica
1 Ningún controlador tiene listas, bucles de búsqueda ni contadores Búscalos
2 Ningún controlador contiene una regla de negocio Léelos entero
3 Ningún service menciona HTTP, códigos, DTO ni ResponseEntity Busca Response en el paquete
4 Ningún repository conoce reglas de negocio Léelos
5 No queda ningún new de un colaborador Busca new en controller y service
6 Todas las dependencias se piden por constructor y son final Léelas
7 Los repositorios son interfaces Míralos
8 Cada clase lleva el estereotipo de su capa Míralos
9 Cada caso de uso es un método público con nombre de negocio Lee los nombres en voz alta
10 Cada regla de negocio tiene su test Cuenta reglas y cuenta tests
Estoy atascado · el controlador de la ruta anidada

GET /proyectos/{id}/tareas es el que suele quedarse a medias, porque toca dos recursos y es tentador resolverlo con dos llamadas desde el controlador.

Si tu controlador llama a dos servicios y decide algo entre medias, eso es coordinación, y la coordinación es del service. Decide en cuál vive el caso de uso y déjalo ahí entero.

Paso 3 · La doble comprobación

Ejecuta primero los tests del servicio con el backend detenido; su resultado debe depender de los objetos preparados por los tests. Después arranca el backend y ejecuta la colección HTTP con sus propios datos. Si falla un test, revisa regla y doble de prueba; si los tests pasan y falla HTTP, sigue la petición por controlador, mapper y servicio. Registra ambos resultados, porque comprueban límites distintos.

La colección

Demuestra que no has cambiado nada para quien consume la API. Es la prueba de que fue una refactorización.

Los tests

Demuestran que las reglas siguen siendo las que decidiste, y lo demostrarán otra vez dentro de seis meses.

Ambas deben superarse. Existe una tercera comprobación, la más exigente:

La prueba del cambio pequeño

Elige uno de estos y cronométralo de verdad:

  1. Que una tarea nueva nazca con prioridad media.
  2. Publicar un campo nuevo en la respuesta de proyectos.
  3. Añadir un filtro por prioridad al listado de tareas.

Apunta cuántos archivos has tenido que abrir y cuánto has tardado. Compáralo con la estimación que hiciste en el apartado 4 de el análisis de problemas, cuando todo estaba en el controlador. Esa diferencia es el resultado de la unidad.

Paso 4 · Preparar la evidencia de esta versión

  1. El proyecto con la estructura de la especificación.
  2. el análisis de problemas revisado, con cada línea tachada o justificada.
  3. Los tests, con al menos uno por regla de negocio, en verde con ./mvnw test.
  4. La colección, en verde y sin ninguna petición modificada desde la UD3.
  5. las decisiones técnicas ampliado con tres:
    • Dónde vive el caso de uso de la ruta anidada y por qué.
    • Qué código de estado devuelve una regla de negocio incumplida en tu API, y por qué ese.
    • Qué regla te costó más colocar y qué duda tuviste.

Paso 5 · Autoevaluación · pásale el código a otro

Intercambia el enlace a una versión concreta del repositorio. Clónala en otra carpeta, abre su README y prepara su configuración antes de ejecutar los comandos. Responde a las preguntas de la revisión señalando clase y método, no solo el nombre de una capa. Devuelve los pasos que faltaban en el README y una petición que reproduzca cada defecto encontrado; aplica después las correcciones equivalentes a tu proyecto.

  1. Intercambia el proyecto con un compañero.
  2. Sin preguntarle nada, y solo mirando los nombres de las clases y de los métodos, que responda por escrito:
    • ¿Dónde se decide qué prioridad tiene una tarea nueva?
    • ¿Dónde habría que tocar para cambiar de almacenamiento?
    • ¿Dónde se decide qué código de estado devuelve un error?
    • ¿Qué reglas de negocio tiene esta aplicación?
  3. Cada respuesta equivocada señala un nombre confuso o una responsabilidad mal colocada. Anótalas.
  4. Corrige tu proyecto con lo que salga de ahí.

La cuarta pregunta es la mejor: si tu compañero puede enumerar tus reglas de negocio leyendo los nombres de tus métodos y tus tests, la arquitectura está haciendo su trabajo.

Paso 6 · Lo que sigue faltando

Lo que sigue mal Se arregla en
Al reiniciar se pierde todo UD5, con PostgreSQL
Buscar recorre la lista entera, una por una UD5, con consultas
No hay forma de relacionar datos más allá de guardar un id UD5, con relaciones
Nadie garantiza que dos operaciones simultáneas no se pisen UD5, con transacciones

Conviene observar lo que no aparece en esa tabla: ni el contrato, ni las reglas, ni la estructura. Eso ya está.

Por qué la UD5 va a ser más fácil de lo que parece

Tu service pide una interfaz. En la UD5 se borra la implementación en memoria y se pone otra que habla con PostgreSQL.

El service, el controller, los DTO, el mapper y los tests no se tocan. Cambiar la base de datos entera va a ser un cambio localizado, y eso es exactamente lo que has construido estas dos semanas.

Objetivo mínimoLos diez criterios cumplidos y las dos comprobaciones en verde.
Si lo tienesel análisis de problemas tachado línea a línea y la prueba del cambio pequeño cronometrada.
RetoLa revisión cruzada con un compañero, con las respuestas equivocadas convertidas en correcciones.
Ver respuestas

1 · Porque deja dos formas de hacer lo mismo conviviendo, y quien llegue después no sabrá cuál es la buena ni por qué hay dos.

2 · La colección demuestra que el comportamiento observable no ha cambiado. Los tests demuestran que las reglas de negocio siguen siendo las decididas, y lo seguirán demostrando en el futuro.

3 · La implementación del repositorio. El service, el controller, los DTO, el mapper y los tests se quedan como están.

4 · El coste real de mantener el código: cuántos archivos hay que abrir y cuánto se tarda en un cambio pequeño, comparado con lo que costaba antes.

Paso 7 · Comprobar y registrar el resultado del proyecto

  1. Los tests del servicio y la colección deben pasar después de la revisión sin cambiar el contrato acordado.
  2. Pide a otra persona que localice almacenamiento, regla y respuesta de una operación. Registra cualquier dependencia entre capas que aún debas corregir.

Cierre

15 minutos · resultado comprobable y explicación individual

Al terminar la sesión:

La versión en capas supera las comprobaciones anteriores y permite justificar la ubicación de cada regla.

Cada integrante explica una decisión del código apoyándose en una de las comprobaciones realizadas.