04 - API First: el contrato antes del código

En el hito de partida la aplicación se construyó primero en código y el contrato quedó implícito: nadie ajeno al código podía conocer GET /api/products sin leer su implementación. Este hito aplica el tema 02 — API First: toda la API del módulo de catálogo — ahora con catálogos y con la paginación que el listado plano ya necesita — se diseña y se revisa antes de implementarla, y el contrato — un documento OpenAPI — pasa a ser la fuente de verdad.

Pieza Cambio en este hito
Contrato Nace openapi.yaml (v0.1.0): catálogos, productos, listado paginado y reglas 409
controller El listado plano de la partida desaparece; las operaciones nuevas se implementan desde el contrato
Herramientas El esqueleto se genera con openapi-generator; Swagger UI (springdoc) lo hace navegable y ejecutable
  1. Redactar openapi.yaml con la API completa del módulo de catálogo:
Operación Petición Respuestas
Listado de catálogos GET /api/catalogs 200 · Catalog[]
Ficha de catálogo GET /api/catalogs/{id} 200 · 404
Alta de catálogo POST /api/catalogs 201
Modificación de catálogo PUT /api/catalogs/{id} 200 · 404
Borrado de catálogo DELETE /api/catalogs/{id} 204 · 404 · 409
Productos de un catálogo GET /api/catalogs/{id}/products?page&size 200 · 404
Ficha de producto GET /api/products/{id} 200 · 404
Alta de producto POST /api/products 201 · 404
Modificación de producto PUT /api/products/{id} 200 · 404
Borrado de producto DELETE /api/products/{id} 204 · 404
  1. Esquemas: Catalog y CatalogRequest; Product (respuesta, con id y catalogId) y ProductRequest (con catalogId, sin id); ProductPage para el listado paginado del catálogo — content más los metadatos page, size, totalElements y totalPages; y Problem (RFC 9457: type, title, status, detail) para los errores. Los 404 de catálogo o producto inexistente y los 409 de estado — nombre de catálogo repetido, catálogo con productos — se declaran también en el contrato.
  2. La paginación se define en el contrato: page (desde 0, por defecto 0) y size (por defecto 10) como parámetros de GET /api/catalogs/{id}/products; la respuesta lleva siempre los metadatos.
  3. Aún sin constraints de validación: llegan en el hito 05; la especificación de este hito describe las operaciones y sus errores de estado, no el formato de los datos.
  4. Esta primera versión se redacta y se revisa antes de generar código: es el momento de acordar el contrato.
  5. El documento se guarda en src/main/resources/openapi.yaml, se versiona en el repositorio y su info.version sube en cada hito que toque la API.
El listado plano de la partida desaparece: veintiocho productos en una sola respuesta no escala y no deja navegar por catálogos. El contrato lo sustituye por el subrecurso paginado GET /api/catalogs/{id}/products. Es la primera decisión que el contrato toma sobre el código.
  • El generador openapi-generator — integrado como plugin de Maven del modo que muestra el tema 02 — produce, como código fuente que nunca se edita a mano, las interfaces de la API y los elementos del esquema del contrato.
  • Regenerar con mvn compile tras cada cambio del openapi.yaml: el esqueleto resultante es la guía de lo que queda por implementar.
  • Cada operación nueva baja por las capas de la partida: métodos nuevos en los servicios y SQL de inserción, modificación o borrado en la persistencia JDBC; el mecanismo sigue siendo el de 1.º DAW.
  • El listado de productos de un catálogo sale paginado: el corte y los metadatos (page, size, totalElements, totalPages) se resuelven con JDBC a mano — sin Spring Data, que llega con el hito 07. El contrato exige la respuesta completa con sus metadatos en cada listado.
  • Los estados declarados en el contrato se cumplen: 404 para catálogo o producto inexistente y para el producto cuyo catalogId apunta a un catálogo que no existe; 409 si el nombre del catálogo se repite al crear o modificar, y si se intenta borrar un catálogo con productos (la comprobación, antes del borrado).
  • springdoc monta la doble vista del contrato: el documento generado desde el código en /v3/api-docs y la UI ejecutable en /swagger-ui.html, para revisar y probar cada operación.
  • Swagger UI muestra catálogos y productos y permite ejecutar cada operación, incluida la paginación.
  • Las operaciones responden según el contrato (200 / 201 / 204 / 404 / 409 donde toque).
  • El listado paginado devuelve los metadatos correctos: el catálogo Periféricos (12 productos) reparte en 2 páginas con size 10.
  • Borrar un catálogo con productos responde 409; repetir su nombre también.
  • El esqueleto del contrato — interfaces y esquemas — está generado y no se ha editado a mano.
  • El openapi.yaml está en el repositorio con info.version 0.1.0.
  • Commit y tag hito-04.
A partir de ahora el contrato manda: todo cambio de la API se escribe primero en openapi.yaml y se regenera. Los hitos que no tocan la API no lo tocan.

Siguiente hito: hito 05 — Validación e invariancias.

  • clase/daw/dws/1eval/practicas/p4.txt
  • Última modificación: 2026/10/28 13:31
  • por cesguiro