← Proyecto del primer trimestre

Sesión 28 · Semana 14

Revisión y defensa del backend en producción

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

Se explica

25 minutos · explicación y demostración

Ya has revisado los criterios del primer trimestre. Hoy defenderás cómo funciona el backend y comprobarás que otra persona puede verificarlo. En Servidor explicarás código, reglas, persistencia y pruebas; en Intermodular se evalúa el flujo seguido para publicar esa versión.

Esta demostración es común con Intermodular 14. Relaciona la explicación técnica con las evidencias de proceso del mismo producto. El bloque de cinco minutos descrito abajo corresponde a la parte técnica, no a una segunda defensa independiente.

La revisión de código no es buscar erratas

En muchas empresas novatas la revisión de código se limita a mirar si faltan espacios o si los nombres de variables son bonitos. Eso es una pérdida de tiempo que debería resolver un formateador automático.

Un Code Review de ingeniería de software audita la salud estructural y la viabilidad técnica del sistema a través de cinco vectores críticos:

Los cinco vectores de una auditoría backend
  1. 1. Arquitectura (capas desacopladas)
  2. 2. Persistencia (LAZY, N+1, transacciones)
  3. 3. Seguridad y Contrato (validación DTOs)
  4. 4. Manejo de Errores (códigos semánticos)
  5. 5. Calidad de Tests (sin mocks en BD)
Vector de auditoría Qué debes buscar activamente en el código ajeno
1 · Arquitectura y Capas ¿Se cuelan entidades @Entity en las respuestas de los controladores? ¿Hay llamadas a repositorios desde el controlador sin pasar por el servicio? ¿El servicio conoce clases web o códigos HTTP?
2 · Persistencia y Rendimiento ¿Hay relaciones con FetchType.EAGER? ¿Se usa List en @ManyToMany? ¿Están los métodos de escritura cubiertos por @Transactional(rollbackFor = Exception.class)? ¿Hay riesgo evidente de problema N+1?
3 · Validación y Contrato ¿Tienen los DTOs anotaciones Bean Validation (@NotBlank, @NotNull, @Size)? ¿Lleva el controlador @Valid en los @RequestBody? ¿Se devuelven cabeceras Location en los POST?
4 · Manejo de Errores ¿La API devuelve códigos de estado coherentes (404 para no encontrado, 409 para conflicto de unicidad, 400 para validación)? ¿Se evitan errores 500 con trazas de pila expuestas al cliente?
5 · Batería de Pruebas ¿La suite compila y pasa al 100 % con ./mvnw test? ¿Los tests de repositorio usan TestEntityManager con flush() y clear() para evitar falsos positivos de caché?

Los niveles de severidad en la revisión de código

Para que la revisión sea profesional, constructiva y trazable, clasificamos cada observación según su nivel de severidad (ya sea como comentarios en la Pull Request de GitHub o en las notas de revisión del aula):

🔴 Bloqueante (Blocker)
Fallos graves de integridad, corrupción de datos, consultas N+1 masivas, exposición de secretos o ausencia de validación que provoca errores 500 no capturados. El código no puede fusionarse hasta que se resuelva.
🟡 Mayor (Major)
Violación de separación de capas (ej: DTOs dentro del servicio), ausencia de rollbackFor = Exception.class o tests con aserciones frágiles.
🟢 Sugerencia (Nitpick)
Oportunidades de simplificación con streams, nombres de métodos más expresivos o mejoras en el README.

Ejemplo de observación técnica bien formulada:

### [🔴 Bloqueante] Riesgo de problema N+1 en GET /tareas
* **Ubicación:** `TareaService.java`, línea 42.
* **Problema:** Se llama a `tareaRepo.findAll()` y en el bucle del mapper se accede a `t.getProyecto().getNombre()`. Al estar configurado `FetchType.LAZY`, esto provocará una consulta SQL adicional a PostgreSQL por cada tarea devuelta.
* **Propuesta de solución:** Añadir en `TareaRepository` un método con `@Query("SELECT t FROM Tarea t JOIN FETCH t.proyecto")` para recuperar la relación en una única sentencia SQL unificada.

Se trabaja

140 minutos · implementación guiada sobre el proyecto propio

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

  1. Abre el repositorio y la URL del backend. Identifica el mismo commit en las evidencias de la versión que vas a defender.
  2. Prepara datos de demostración y selecciona una operación completa, una regla rechazada y una consulta con relaciones.
  3. Localiza el controlador, servicio, repositorio y test de esa operación para poder recorrerlos sin buscar durante la explicación.

Paso 2 · El protocolo de la defensa técnica individual (5 minutos cronometrados)

Prepara una secuencia breve en tu colección: consulta correcta, escritura válida, regla rechazada y una consulta que use relaciones. Abre también los métodos que las atienden. Ensaya con un compañero: uno ejecuta y explica; el otro comprueba que la respuesta y la versión corresponden al repositorio entregado. Si aparece un fallo, registra la petición exacta y corrige su causa antes de volver a ensayar. No memorices respuestas sobre una arquitectura distinta de la tuya.

El tiempo se reparte con precisión militar:

[ Minuto 1 ]  Visión general: arquitectura de capas y modelo relacional en PostgreSQL.
[ Minuto 2 ]  La decisión técnica más difícil: qué problema tuviste y cómo lo resolviste.
[ Minuto 3 ]  Evidencia de bitácora: muestra un bloqueo técnico real que superaste y su solución.
[ Minuto 4 ]  Demostración en vivo: ejecución de ./mvnw test y petición real en Bruno con SQL.
[ Minuto 5 ]  Pregunta sorpresa del tribunal: respuesta conceptual y justificación teórica.

El principio de honestidad técnica

Si el tribunal te señala un error o limitación en tu diseño, jamás inventes una excusa ni intentes taparlo.

Un ingeniero profesional responde: «Tienes razón; en esta versión priorizamos X y aceptamos ese compromiso técnico. Para solucionarlo en producción implementaríamos Y mediante este cambio...». Esa respuesta demuestra madurez y dominio real de la materia.

Paso 3 · Auditoría cruzada y refactorización

Clona la versión de otro equipo en otra carpeta y utiliza una base de desarrollo propia, configurada como indica su README. Ejecuta primero los tests y después la colección, con el backend encendido. Para cada observación escribe requisito, archivo o petición, resultado esperado y observado. Corrige después tu propio proyecto con esos mismos criterios, una observación cada vez, y actualiza el registro de la sesión en GitHub.

  1. Clona el repositorio de tus compañeros en una carpeta independiente.

  2. Ejecuta ./mvnw test para verificar si su suite pasa en verde a la primera.

  3. Abre su código y revisa los cinco vectores de auditoría con la tabla anterior.

  4. Deja al menos un aspecto positivo bien resuelto y tres observaciones técnicas justificadas categorizadas por severidad (como comentarios en su Pull Request de GitHub o en la sesión de revisión de aula).

  5. Revisa las observaciones que te han dejado tus revisores.

  6. Aplica las correcciones a las observaciones bloqueantes y mayores.

  7. Vuelve a ejecutar ./mvnw test para asegurar que nada se ha roto.

  8. Haz un commit de entrega final: git commit -m "refactor(review): resolver observaciones de auditoria tecnica".

Prepara tu guion de 5 minutos asegurándote de tener la terminal lista con PostgreSQL arrancado, el proyecto corriendo y las peticiones preparadas en pestañas.

Estructura el guion en cuatro bloques breves, y para cada uno ten preparado qué vas a enseñar en pantalla mientras hablas:

Tiempo Qué cuentas Qué enseñas mientras
0–1 min El modelo: qué entidades hay y cómo se relacionan El diagrama y las clases @Entity
1–3 min El camino feliz completo La colección ejecutándose: alta, consulta y borrado
3–4 min Un caso de error de verdad Un 400 de validación y un 404, con su cuerpo RFC 7807
4–5 min Qué no está terminado La lista de deuda técnica

Las tres preguntas que caen casi siempre en esta primera defensa, y que conviene llevar preparadas:

  • «Enséñame dónde está la regla de negocio.» No se contesta con palabras: se abre el service y se señala el método.
  • «¿Por qué este endpoint devuelve 404 y este otro 409?» Es la pregunta que comprueba si entendiste la UD3 o si copiaste los códigos.
  • «Si te pido cambiar de PostgreSQL a otra base de datos, ¿qué tendrías que tocar?» La respuesta correcta señala que el service no cambia, y es la prueba de que la arquitectura de la UD4 sirvió para algo.
Cómo saber que lo has terminado
Tu proyecto arranca desde cero en la máquina del equipo revisor; has dejado y recibido observaciones categorizadas por severidad; las bloqueantes están corregidas y la suite sigue en verde; y has ensayado la defensa entera con el cronómetro delante al menos una vez.

Paso 4 · Comprobar y registrar el resultado del proyecto

  1. Reproduce el caso permitido y el rechazado, y explica qué capa decide cada resultado y qué datos quedan almacenados.
  2. Haz que otra persona siga el README y registre cualquier paso que falte. Incorpora la corrección y deja el commit final de la revisión identificado.

Ampliación si has completado el trabajo

Primero termina y verifica los pasos anteriores. Estos retos profundizan en el mismo contenido; no sustituyen la entrega ni obligan a iniciar otro proyecto.

Reto · El simulador de preguntas de tribunal técnico

Ensaya tu respuesta a estas tres preguntas típicas de tribunal de evaluación y entrevistas técnicas:

  • Pregunta del tribunal: «Veo que en tus consultas de lectura pones @Transactional(readOnly = true). ¿Qué optimización concreta hace Hibernate y el driver JDBC con esa anotación?»

  • (Respuesta esperada: Hibernate desactiva el dirty checking sobre las entidades leídas, ahorrando ciclos de CPU y memoria RAM al no tener que mantener copias de comparación para actualización).

  • Pregunta del tribunal: «Si mañana el equipo de frontend te pide que en la respuesta de GET /proyectos/{id} el campo activo se llame estaHabilitado, ¿cuántos archivos de tu aplicación tendrías que modificar?»

  • (Respuesta esperada: Únicamente el DTO ProyectoResponse y el ProyectoMapper. La entidad JPA, la base de datos PostgreSQL y las reglas del servicio permanecen 100 % inalteradas gracias a la arquitectura desacoplada).

  • Pregunta del tribunal: «¿Qué ocurriría si dos peticiones HTTP intentan crear simultáneamente un proyecto con el mismo nombre en el mismo milisegundo?»

  • (Respuesta esperada: Ambas pasarían la validación del servicio existsByNombre, pero la restricción física UNIQUE de PostgreSQL abortaría una de ellas con DataIntegrityViolationException, garantizando la integridad de datos).

Objetivo mínimoRevisión de código completada con observaciones técnicas fundamentadas en los 5 vectores.
Si lo tienesRefactorizaciones del feedback aplicadas con tests en verde y guion de defensa de 5 minutos preparado.
RetoDefensa técnica superada con demostración en vivo de peticiones HTTP, logs SQL y respuesta solvente a la pregunta sorpresa.
Ver respuestas

1 · Bloqueante (Blocker: impide la fusión hasta solucionarse), Mayor (Major: problema de arquitectura o robustez importante) y Sugerencia (Nitpick: mejora de estilo o simplificación menor).

2 · Porque acopla el contrato público de la API al esquema físico de la base de datos, puede provocar bucles infinitos de serialización JSON (StackOverflowError) y expone datos internos no deseados.

3 · Desactiva el mecanismo de Dirty Checking (Hibernate no toma una instantánea en memoria de la entidad para comparar cambios al cerrar la transacción, ahorrando memoria y tiempo de CPU).

4 · Reconociendo con sinceridad el límite del conocimiento puntual, explicando qué hipótesis técnica tiene y describiendo cómo investigaría o verificaría la solución en la documentación oficial.

Cierre

15 minutos · resultado comprobable y explicación individual

Al terminar la sesión:

Se entrega la misma versión en ambos módulos: aquí se evalúan código y funcionamiento; en Intermodular, workflow, CI, revisión y puesta en producción.

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