clase:daw:daw-proyecto:tema04
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previa | |||
| clase:daw:daw-proyecto:tema04 [2026/10/14 13:27] – Forma B aclarada: en modo plan el agente escribe plan_<algo>.md en el worktree (fuera de .kiro), se sale del modo plan, y la implementación va en otra conversación con /clear y /code impl para no arrastrar el contexto de planificar claude | clase:daw:daw-proyecto:tema04 [2026/10/14 14:08] (actual) – Tema nuevo «2. IA y agentes»: los temas 2 a 7 pasan a ser 3 a 8, con sus referencias cruzadas renumeradas claude | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| - | ====== 4. IA en el proyecto ====== | + | ====== 4. Docker |
| - | Objetivo del tema: usar bien al agente para programar. No se enseña a programar; se enseña a **pedir** el trabajo como una especificación | + | Objetivo del tema: cada worktree tiene **su propia aplicación completa funcionando** (base de datos, backend |
| - | Lo que ya está contado en el [[cursos:sdd:start|curso de programación con IA]] y aquí no se repite: qué es el [[cursos:sdd:10-spec-driven-development|Spec-driven development]] y por qué encaja con los agentes, [[cursos:sdd:11-kiro|cc-sdd (Kiro)]] con sus fases y su memoria del proyecto, | + | Lo que ya sabéis y aquí no se repite: imágenes y contenedores ([[clase: |
| - | ===== Dos caminos: spec para los CRUD, plan para el resto ===== | + | ===== Tres contenedores |
| - | En este proyecto hay dos clases | + | La aplicación son tres contenedores, |
| - | * **Un CRUD** (una entidad con su listado, alta, edición y borrado) va por **especificación**: | + | ^ Servicio ^ Imagen ^ Qué hace ^ |
| - | * **Todo lo demás** (un filtro, un informe, una regla de negocio, un cambio | + | | '' |
| + | | '' | ||
| + | | '' | ||
| - | En los dos, la regla es la misma: primero un fichero que el alumno lee y corrige, después la implementación con el contexto limpio. | + | El navegador solo habla con '' |
| - | La spec la genera | + | Los dos Dockerfile son **multi-stage** y los escribe la IA. Lo único que hay que vigilar: |
| - | <code> | + | <sxh bash; |
| - | npx cc-sdd@latest | + | FROM maven:3.9-eclipse-temurin-25 AS build |
| - | </code> | + | WORKDIR /app |
| + | COPY pom.xml . | ||
| + | RUN --mount=type=cache, | ||
| + | COPY src ./src | ||
| + | RUN --mount=type=cache, | ||
| - | Ese es el flujo de cada issue: | + | FROM eclipse-temurin:25-jre |
| + | RUN apt-get update && apt-get install -y curl && rm -rf / | ||
| + | COPY --from=build / | ||
| + | ENTRYPOINT [" | ||
| + | </ | ||
| - | < | + | El '' |
| - | start | + | |
| - | :/git-flow start N | + | |
| - | y ./app.sh start; | + | |
| - | if (¿es un CRUD?) then (sí) | + | |
| - | :/sdd spec create | + | |
| - | requisitos, diseño y tareas | + | |
| - | en .kiro/ | + | |
| - | :Leer y corregir los tres ficheros; | + | |
| - | :/clear y /git-flow update; | + | |
| - | :/sdd spec impl | + | |
| - | una tarea tras otra; | + | |
| - | else (no) | + | |
| - | :Modo plan: el agente lee el código | + | |
| - | y escribe plan_< | + | |
| - | :Leer y corregir el plan; | + | |
| - | | + | |
| - | :/code impl plan_< | + | |
| - | una tarea tras otra; | + | |
| - | endif | + | |
| - | :Tests unitarios y de arquitectura | + | |
| - | después de cada tarea; | + | |
| - | :Probar en el navegador; | + | |
| - | stop | + | |
| - | </ | + | |
| - | ==== /sdd spec create ==== | + | <sxh bash; |
| + | FROM node:22 AS build | ||
| + | WORKDIR /app | ||
| + | COPY package*.json . | ||
| + | RUN npm ci | ||
| + | COPY . . | ||
| + | RUN npx ng build --configuration production | ||
| - | Se lanza en el worktree del issue, sin argumentos: el número del issue está en el nombre de la rama. Lo que hace, por dentro, son las cuatro fases de cc-sdd encadenadas: | + | FROM nginx:alpine |
| + | COPY nginx.conf / | ||
| + | COPY --from=build / | ||
| + | </ | ||
| - | - '' | + | <sxh plain; |
| - | - ''/ | + | server { |
| - | - '' | + | |
| - | - ''/ | + | root /usr/share/nginx/html; |
| - | Y se para. El resultado son tres ficheros en '' | + | location |
| + | proxy_pass http://backend:8080/ | ||
| + | } | ||
| - | **Revisar esos ficheros es el trabajo humano del flujo.** Es mucho más barato corregir una frase de la spec que corregir el código que sale de ella. Qué mirar en cada uno: | + | location / { |
| + | try_files $uri $uri/ /index.html; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| - | ^ Fichero ^ Qué tiene que tener ^ | + | El '' |
| - | | '' | + | |
| - | | '' | + | |
| - | | '' | + | |
| - | Si se cambia algo en '' | + | ===== Producción |
| - | ==== /sdd spec impl ==== | + | Docker Compose carga '' |
| - | Conversación nueva ('' | + | * '' |
| + | * '' | ||
| - | <code> | + | <sxh yaml; |
| - | /sdd spec impl | + | services: |
| - | </code> | + | db: |
| + | image: mariadb: | ||
| + | environment: | ||
| + | MARIADB_DATABASE: | ||
| + | MARIADB_USER: | ||
| + | MARIADB_PASSWORD: | ||
| + | MARIADB_ROOT_PASSWORD: | ||
| + | volumes: | ||
| + | - db-data:/var/ | ||
| + | networks: | ||
| + | - interna | ||
| + | healthcheck: | ||
| + | test: [" | ||
| + | interval: 5s | ||
| + | retries: 20 | ||
| - | Por dentro es '' | + | backend: |
| + | build: ./backend | ||
| + | environment: | ||
| + | SPRING_DATASOURCE_URL: | ||
| + | SPRING_DATASOURCE_USERNAME: | ||
| + | SPRING_DATASOURCE_PASSWORD: | ||
| + | depends_on: | ||
| + | db: | ||
| + | condition: service_healthy | ||
| + | networks: | ||
| + | | ||
| + | healthcheck: | ||
| + | | ||
| + | interval: 5s | ||
| + | retries: 20 | ||
| - | Solo implementa la spec. Los planes (abajo) y las correcciones de una revisión (tema 5) se hacen con '' | + | frontend: |
| + | build: | ||
| + | environment: | ||
| + | VIRTUAL_HOST: | ||
| + | depends_on: | ||
| + | backend: | ||
| + | condition: service_healthy | ||
| + | networks: | ||
| + | - interna | ||
| + | - proxy | ||
| - | Por qué el ''/ | + | volumes: |
| + | db-data: | ||
| - | ==== El modo plan y /code impl: lo que no es un CRUD ==== | + | networks: |
| + | interna: | ||
| + | proxy: | ||
| + | external: true | ||
| + | name: nginx-proxy-network | ||
| + | </ | ||
| - | Claude Code y OpenCode tienen un **modo plan** en el que el agente solo lee: explora el código, piensa y propone, pero no toca nada. En Claude Code se entra con '' | + | Los '' |
| - | - En el worktree del issue, modo plan, y se le dice lo que se quiere (lo que pone el issue) y que escriba el plan como **lista de tareas** ('' | + | <sxh yaml; |
| - | | + | services: |
| - | - Se lee y se corrige a mano, igual que una spec: tareas pequeñas, en orden, y que no falte ninguna pantalla ni ningún caso de error. | + | |
| - | | + | |
| + | | ||
| - | < | + | backend: |
| - | /code impl plan_filtro-provincia.md | + | |
| - | </ | + | |
| + | | ||
| + | SPRING_PROFILES_ACTIVE: | ||
| - | Por qué en dos conversaciones y no seguidas: al planificar, el agente ha leído medio proyecto y ha descartado alternativas, | + | frontend: |
| + | build: | ||
| + | target: build | ||
| + | command: npx ng serve --host 0.0.0.0 --proxy-config proxy.conf.json | ||
| + | volumes: | ||
| + | - ./ | ||
| + | - / | ||
| + | ports: | ||
| + | - " | ||
| + | </ | ||
| - | ''/ | + | Lo que cambia |
| - | La skill '' | + | * **Se publican los puertos**, para entrar desde el navegador y para que Maven y Playwright lleguen a la base de datos y al frontend desde el host. |
| + | * **El frontend pasa a '' | ||
| + | * **El backend no tiene recarga en caliente**: cada cambio en Java es '' | ||
| + | * **Datos de prueba** activados (abajo). | ||
| - | ==== La carpeta de la spec ==== | + | <note important> |
| - | '' | + | ===== Un compose por worktree ===== |
| - | Es un **registro** de lo que se pidió, no documentación: | + | Dos worktrees con el mismo '' |
| - | < | + | < |
| - | .kiro/ | + | COMPOSE_PROJECT_NAME=mi-proyecto-12-alta-clientes |
| - | </ | + | DB_PORT=33112 |
| - | + | BACKEND_PORT=8112 | |
| - | ==== La skill /sdd ==== | + | FRONTEND_PORT=4212 |
| - | + | DB_PASSWORD=dev | |
| - | Es corta, porque el trabajo lo hacen los comandos de cc-sdd. Recibe el subcomando en '' | + | |
| - | + | ||
| - | < | + | |
| - | --- | + | |
| - | name: sdd | + | |
| - | description: | + | |
| - | allowed-tools: | + | |
| - | --- | + | |
| </ | </ | ||
| - | Todas las skills | + | * '' |
| + | * Los puertos los busca ''/ | ||
| + | * Las variables llevan valor por defecto, | ||
| - | ===== El primer CRUD ===== | + | ''/ |
| - | La práctica central del tema es el primer CRUD del proyecto, hecho con ''/ | + | ===== La primera tabla ===== |
| - | Se resuelve | + | Hasta ahora el backend no tiene base de datos. |
| - | ===== El steering: las dos arquitecturas ===== | + | * Dependencias '' |
| + | * Una migración '' | ||
| + | * Un '' | ||
| - | Para que el segundo CRUD salga igual que el primero | + | El esquema |
| - | ==== Cuándo se genera | + | ===== Datos de prueba ===== |
| - | ''/ | + | Cada worktree arranca con la base de datos vacía: no hay nada que ver en la aplicación ni se pueden escribir tests E2E que dependan de que exista |
| < | < | ||
| - | /kiro-steering | + | backend/src/ |
| + | ├── migration/ | ||
| + | └── datos-prueba/ | ||
| </ | </ | ||
| - | Los tres ficheros que genera, | + | Los de '' |
| - | ==== Dos arquitecturas, | + | <sxh plain; |
| - | + | spring.flyway.locations=classpath:db/ | |
| - | Lo específico de cada parte no va en esos tres, sino en dos ficheros de steering **condicionales**, | + | |
| - | + | ||
| - | <sxh plain; | + | |
| - | --- | + | |
| - | inclusion: fileMatch | + | |
| - | fileMatchPattern: " | + | |
| - | --- | + | |
| - | # Arquitectura del servidor | + | |
| - | ... | + | |
| </ | </ | ||
| - | Y '' | + | * En desarrollo el perfil lo activa |
| + | | ||
| + | * Para volver al estado inicial (antes de pasar los E2E, por ejemplo): '' | ||
| - | ^ '' | + | Cada entidad |
| - | | Las capas '' | + | |
| - | | Nombres: '' | + | |
| - | | Dónde se valida (Bean Validation en el '' | + | |
| - | | Migraciones | + | |
| - | | Cómo se prueban los unitarios: JUnit 5 y Mockito, sin Spring | '' | + | |
| - | La lección: **lo que el steering no dice, el agente lo inventa distinto cada vez.** Si el segundo CRUD sale distinto del primero, falta una línea en el steering, no un prompt mejor. | + | ===== El script app.sh ===== |
| - | ==== Las skills | + | Operar la aplicación es siempre lo mismo y no necesita ninguna inteligencia, |
| - | El steering solo lo leen los comandos de cc-sdd. Las demás skills del proyecto (''/ | + | < |
| - | + | #!/bin/bash | |
| - | < | + | # La aplicación de este worktree: start | stop [-v] | status | logs |
| - | --- | + | set -e |
| - | name: convenciones-backend | + | cd " |
| - | description: | + | case " |
| - | --- | + | start) |
| - | Lee .kiro/ | + | docker network inspect nginx-proxy-network >/dev/null 2>&1 || docker network create nginx-proxy-network |
| + | | ||
| + | | ||
| + | echo " | ||
| + | stop) shift; docker compose down " | ||
| + | | ||
| + | logs) | ||
| + | *) echo "uso: $0 start | stop [-v] | status | logs"; exit 1 ;; | ||
| + | esac | ||
| </ | </ | ||
| - | Y '' | + | * '' |
| + | * '' | ||
| + | * '' | ||
| + | * Trabaja sobre la carpeta | ||
| - | ===== El contexto del agente ===== | + | < |
| - | El contexto es todo lo que el modelo tiene delante en una conversación: | + | ===== Dónde corren Maven y los tests ===== |
| - | | + | Las imágenes son de **ejecución**: el backend es un JRE sin Maven y el frontend es Nginx. Así que compilar |
| - | * **El modelo bueno para especificar, | + | |
| - | * **No pegar logs enteros.** Solo el error y las líneas de alrededor. | + | |
| - | | + | |
| - | ===== MCP ===== | + | ^ Qué ^ Dónde ^ Contra qué ^ |
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| - | Dos servidores MCP y ninguno más (qué es un MCP: [[cursos: | + | Son los tres comandos de tests del proyecto. Maven y npm funcionan igual en Linux, Windows y Mac, y son lo que ejecutan el alumno, el agente y CI (tema 7). '' |
| - | * **Context7**: | + | ==== npm run ==== |
| - | * **Playwright MCP**: el agente abre la aplicación en un navegador y la ve. Sirve para que compruebe por sí mismo que una pantalla funciona, y en el tema 5 para generar los tests E2E. | + | |
| - | Se configuran con '' | + | '' |
| - | ===== Permisos del agente ===== | + | <sxh json; |
| - | + | " | |
| - | En el tema 2 se permitió lo básico. Para programar, el agente tiene que poder compilar, pasar tests y levantar la aplicación sin preguntar en cada paso. La lista de '' | + | " |
| + | " | ||
| + | "test:api": " | ||
| + | " | ||
| + | } | ||
| + | </ | ||
| - | * **Permitido**: | + | Los dos scripts resetean la base de datos del worktree, esperan a que la aplicación esté sana y pasan los tests de un proyecto de Playwright |
| - | * **Pregunta**: | + | |
| - | * **Denegado**: | + | |
| - | En OpenCode, lo mismo en la clave '' | + | Esto va en '' |
| ===== Ejercicios ===== | ===== Ejercicios ===== | ||
| ==== Ejercicio 1 ==== | ==== Ejercicio 1 ==== | ||
| - | * Configura Context7 | + | * Crea un issue «Aplicación en Docker» e inícialo con ''/ |
| - | * Comprueba que funcionan: pide al agente la forma actual de declarar una ruta en Angular | + | * Pide al agente los dos '' |
| - | * Completa | + | * Añade '' |
| + | * '' | ||
| + | * Entra en '' | ||
| ==== Ejercicio 2 ==== | ==== Ejercicio 2 ==== | ||
| - | * Crea un issue «Skill /sdd» e inícialo con ''/ | + | * En el mismo worktree, pide al agente que añada JPA, MariaDB y Flyway, la migración '' |
| - | * Instala cc-sdd en la raíz del repositorio | + | * Crea '' |
| - | * Escribe la skill '' | + | * '' |
| - | * Añade a '' | + | * Arranca con '' |
| + | * Cambia un texto de la página de Angular, guarda y comprueba que el navegador se recarga solo. | ||
| ==== Ejercicio 3 ==== | ==== Ejercicio 3 ==== | ||
| - | * Crea un issue para la primera entidad de tu proyecto | + | * Añade a '' |
| - | * '' | + | * Escribe en '' |
| - | * Lee '' | + | * ''/ |
| - | * '' | + | |
| - | * Prueba la aplicación en la URL del worktree: listado, alta, edición, borrado | + | |
| - | * Lee el código generado clase por clase y corrígelo: es la referencia de todos los CRUD que vienen después. | + | |
| ==== Ejercicio 4 ==== | ==== Ejercicio 4 ==== | ||
| - | * En el mismo worktree, lanza '' | + | * Escribe |
| - | * Con '' | + | * Amplía |
| - | * Escribe | + | * Finaliza el issue. |
| - | * ''/ | + | |
| - | * '' | + | |
| - | * Mira ''/ | + | |
| ==== Ejercicio 5 ==== | ==== Ejercicio 5 ==== | ||
| - | * Crea un issue «Skill /code: impl» e inícialo. Escribe la skill ''/ | + | * Crea dos issues cualesquiera, |
| - | * Crea un issue que no sea un CRUD (un filtro en el listado, un campo calculado, un informe) e inícialo. | + | * Cambia los datos de prueba en uno de los dos y comprueba |
| - | * En modo plan, dile lo que quieres | + | * Finaliza los dos y comprueba con '' |
| - | * '' | + | |
clase/daw/daw-proyecto/tema04.txt · Última modificación: por claude
