clase:daw:daw-proyecto:tema04
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| clase:daw:daw-proyecto:tema04 [2026/10/14 01:06] – Referencia de permisos al tema 2 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 | + | 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, los modos Plan y Build de [[cursos:sdd:03-opencode# | + | Lo que ya sabéis y aquí no se repite: imágenes y contenedores ([[clase: |
| - | ===== Mini SDD con el modo plan ===== | + | ===== Tres contenedores |
| - | Los frameworks de SDD completos (OpenSpec, Spec Kit, cc-sdd) generan requisitos, diseño y tareas en documentos separados. Para un proyecto | + | La aplicación son tres contenedores, uno por caja del diagrama C4 de contenedores: |
| - | - **La intención escrita en un fichero** antes de tocar código, revisada por una persona. | + | ^ Servicio ^ Imagen ^ Qué hace ^ |
| - | - **Ejecutarla con el contexto limpio**, | + | | '' |
| + | | '' | ||
| + | | '' | ||
| - | Ese es el flujo de cada issue: | + | El navegador solo habla con '' |
| - | < | + | Los dos Dockerfile son **multi-stage** |
| - | start | + | |
| - | :En el worktree del issue, | + | |
| - | entrar en modo plan; | + | |
| - | :Decir qué se quiere | + | |
| - | que pregunte lo que no esté claro; | + | |
| - | :El agente propone el plan; | + | |
| - | repeat | + | |
| - | :Leerlo y corregirlo; | + | |
| - | repeat while (¿hay algo que cambiar?) is (sí) | + | |
| - | :Salir del modo plan: | + | |
| - | el agente guarda planes/ | + | |
| - | y no hace nada más; | + | |
| - | :/clear; | + | |
| - | :Ejecuta @planes/ | + | |
| - | :El agente implementa y pasa los tests; | + | |
| - | stop | + | |
| - | </ | + | |
| - | ==== 1. Planificar ==== | + | <sxh bash; |
| + | FROM maven: | ||
| + | WORKDIR /app | ||
| + | COPY pom.xml . | ||
| + | RUN --mount=type=cache, | ||
| + | COPY src ./src | ||
| + | RUN --mount=type=cache, | ||
| - | En Claude Code, '' | + | FROM eclipse-temurin: |
| + | RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* | ||
| + | COPY --from=build | ||
| + | ENTRYPOINT [" | ||
| + | </ | ||
| - | Lo que se le dice: | + | El '' |
| - | <code> | + | <sxh bash; |
| - | Quiero implementar el issue #12 (gh issue view 12). Antes de proponer nada, hazme | + | FROM node:22 AS build |
| - | las preguntas que necesites. El resultado de este plan es SOLO el fichero | + | WORKDIR /app |
| - | planes/ | + | COPY package*.json |
| - | </ | + | RUN npm ci |
| + | COPY . . | ||
| + | RUN npx ng build --configuration production | ||
| - | El plan tiene que decir **qué** y **cómo**: | + | FROM nginx:alpine |
| + | COPY nginx.conf / | ||
| + | COPY --from=build / | ||
| + | </ | ||
| - | * Cambios en la base de datos (la migración), | + | <sxh plain; |
| - | * Las decisiones de diseño que haya tomado y por qué. | + | server { |
| - | * Los **criterios de aceptación**: | + | |
| + | root / | ||
| - | **Revisarlo es el trabajo humano del flujo.** Es mucho más barato corregir una frase del plan que corregir el código que sale de ella. Si el plan tiene algo que no convence, se le dice y se repite hasta que esté bien. | + | location /api/ { |
| + | proxy_pass http:// | ||
| + | } | ||
| - | ==== 2. Guardar y limpiar ==== | + | location / { |
| + | try_files $uri $uri/ /index.html; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| - | Al aprobar el plan, el agente guarda | + | El '' |
| - | Por qué: al salir del modo plan, por defecto el agente implementa en la **misma conversación**, | + | ===== Producción |
| - | ==== 3. Ejecutar ==== | + | Docker Compose carga '' |
| - | < | + | * '' |
| - | Ejecuta @planes/12-alta-clientes.md. Al acabar, compila | + | * '' |
| - | </ | + | |
| - | El agente implementa con el contexto limpio: solo tiene '' | + | <sxh yaml;title:compose.yaml> |
| + | services: | ||
| + | db: | ||
| + | image: mariadb: | ||
| + | environment: | ||
| + | MARIADB_DATABASE: | ||
| + | MARIADB_USER: | ||
| + | MARIADB_PASSWORD: | ||
| + | MARIADB_ROOT_PASSWORD: | ||
| + | volumes: | ||
| + | - db-data:/ | ||
| + | networks: | ||
| + | - interna | ||
| + | healthcheck: | ||
| + | test: [" | ||
| + | interval: 5s | ||
| + | retries: 20 | ||
| - | ==== La carpeta planes/ ==== | + | backend: |
| + | build: ./backend | ||
| + | environment: | ||
| + | SPRING_DATASOURCE_URL: | ||
| + | SPRING_DATASOURCE_USERNAME: | ||
| + | SPRING_DATASOURCE_PASSWORD: | ||
| + | depends_on: | ||
| + | db: | ||
| + | condition: service_healthy | ||
| + | networks: | ||
| + | - interna | ||
| + | healthcheck: | ||
| + | test: [" | ||
| + | interval: 5s | ||
| + | retries: 20 | ||
| - | '' | + | frontend: |
| + | build: ./frontend | ||
| + | environment: | ||
| + | VIRTUAL_HOST: | ||
| + | depends_on: | ||
| + | backend: | ||
| + | condition: service_healthy | ||
| + | networks: | ||
| + | - interna | ||
| + | - proxy | ||
| - | Es un **registro** de lo que se pidió, no documentación: cuando el código cambie después, el plan no se actualiza. Para que el agente no se confunda con planes viejos, '' | + | volumes: |
| + | db-data: | ||
| - | < | + | networks: |
| - | planes/ es histórico: la fuente de verdad es el código. No leas planes antiguos salvo que te lo pidan. | + | |
| - | </code> | + | proxy: |
| + | external: true | ||
| + | name: nginx-proxy-network | ||
| + | </sxh> | ||
| - | ==== Cuándo usar el flujo ==== | + | Los '' |
| - | ^ Tamaño del cambio ^ Cómo ^ | + | <sxh yaml; |
| - | | Trivial: un texto, un color, una validación de un campo | Prompt directo, sin plan | | + | services: |
| - | | Todo lo demás | Plan → fichero → ''/ | + | db: |
| - | | Un CRUD | ''/ | + | |
| + | - " | ||
| - | ===== El contexto del agente ===== | + | backend: |
| + | ports: | ||
| + | - " | ||
| + | environment: | ||
| + | SPRING_PROFILES_ACTIVE: | ||
| - | El contexto es todo lo que el modelo tiene delante en una conversación: '' | + | frontend: |
| + | build: | ||
| + | target: build | ||
| + | command: npx ng serve --host 0.0.0.0 --proxy-config proxy.conf.json | ||
| + | volumes: | ||
| + | - ./ | ||
| + | - / | ||
| + | ports: | ||
| + | - " | ||
| + | </ | ||
| - | * **Una conversación por tarea.** ''/ | + | Lo que cambia |
| - | * **El modelo bueno para planificar, el barato para ejecutar** cosas claras. ''/ | + | |
| - | * **No pegar logs enteros.** Solo el error y las líneas de alrededor. | + | |
| - | * **Mirar el contador.** ''/ | + | |
| - | ===== Skills | + | * **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). | ||
| - | El agente escribe código de cualquier manera si no se le dice cómo se hace **en este proyecto**. Y decírselo en cada prompt | + | <note important> |
| - | ^ Skill ^ Qué contiene ^ | + | ===== Un compose |
| - | | '' | + | |
| - | | '' | + | |
| - | La arquitectura es la que ya conocéis de Programación | + | Dos worktrees con el mismo '' |
| - | **Se escriben a partir del código, no de la teoría.** Después del primer CRUD, revisado y corregido hasta que esté como tiene que estar, se le pide al agente: «lee el CRUD de clientes y escribe la skill '' | + | <sxh bash;title:.env> |
| + | COMPOSE_PROJECT_NAME=mi-proyecto-12-alta-clientes | ||
| + | DB_PORT=33112 | ||
| + | BACKEND_PORT=8112 | ||
| + | FRONTEND_PORT=4212 | ||
| + | DB_PASSWORD=dev | ||
| + | </ | ||
| - | La '' | + | * '' |
| + | | ||
| + | | ||
| - | <sxh yaml> | + | ''/ |
| - | --- | + | |
| - | name: convenciones-backend | + | ===== La primera tabla ===== |
| - | description: Cómo se escribe el código | + | |
| - | --- | + | Hasta ahora el backend no tiene base de datos. Se añaden ahora, con un prompt directo al agente (el flujo de trabajo de verdad llega en el tema 5; esto es solo para tener algo que ver): |
| + | |||
| + | * Dependencias '' | ||
| + | * Una migración '' | ||
| + | * Un '' | ||
| + | |||
| + | El esquema **siempre** va en migraciones de Flyway, '' | ||
| + | |||
| + | ===== 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 un cliente. Los datos de prueba se separan | ||
| + | |||
| + | < | ||
| + | backend/ | ||
| + | ├── migration/ | ||
| + | └── datos-prueba/ | ||
| + | </ | ||
| + | |||
| + | Los de '' | ||
| + | |||
| + | <sxh plain; | ||
| + | spring.flyway.locations=classpath: | ||
| </ | </ | ||
| - | ===== MCP ===== | + | * En desarrollo el perfil lo activa '' |
| + | * En producción '' | ||
| + | * Para volver al estado inicial (antes de pasar los E2E, por ejemplo): '' | ||
| - | Dos servidores MCP y ninguno más (qué es un MCP: [[cursos: | + | Cada entidad nueva trae su '' |
| - | * **Context7**: | + | ===== El script app.sh ===== |
| - | * **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 '' | + | Operar la aplicación es siempre lo mismo y no necesita ninguna inteligencia, |
| - | ===== Permisos del agente ===== | + | <sxh bash; |
| + | # | ||
| + | # La aplicación de este worktree: start | stop [-v] | status | logs | ||
| + | set -e | ||
| + | cd " | ||
| + | case " | ||
| + | start) | ||
| + | docker network inspect nginx-proxy-network >/ | ||
| + | docker compose up -d --build --wait | ||
| + | [ -f .env ] && . ./.env | ||
| + | echo " | ||
| + | stop) | ||
| + | status) docker compose ps ;; | ||
| + | logs) | ||
| + | *) echo "uso: $0 start | stop [-v] | status | logs"; exit 1 ;; | ||
| + | esac | ||
| + | </ | ||
| - | En el tema 2 se permitió | + | * '' |
| + | * '' | ||
| + | * '' | ||
| + | * Trabaja sobre la carpeta en la que está y lee su '' | ||
| + | |||
| + | < | ||
| + | |||
| + | ===== Dónde corren Maven y los tests ===== | ||
| + | |||
| + | Las imágenes son de **ejecución**: | ||
| + | |||
| + | ^ Qué ^ Dónde ^ Contra qué ^ | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | |||
| + | 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). '' | ||
| + | |||
| + | ==== npm run ==== | ||
| + | |||
| + | '' | ||
| + | |||
| + | <sxh json;title:frontend/ | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | </ | ||
| - | * **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 para la primera entidad de tu proyecto con un CRUD completo (por ejemplo «CRUD | + | * En el mismo worktree, pide al agente que añada JPA, MariaDB y Flyway, |
| - | * Entra en modo plan y pide el plan con el prompt del tema: que pregunte lo que no esté claro y que el resultado sea solo '' | + | * Crea '' |
| - | * Lee el plan. Comprueba que tiene migración, clases por capas, componentes | + | * '' |
| - | * Sal del modo plan, comprueba que el fichero existe y que el agente no ha tocado nada más. | + | * Arranca con '' |
| - | * '' | + | * Cambia un texto de la página |
| - | * Prueba la aplicación en la URL del worktree: listado, alta, edición, borrado | + | |
| - | * Lee el código generado clase por clase: es la referencia | + | |
| ==== Ejercicio 3 ==== | ==== Ejercicio 3 ==== | ||
| - | * Pide al agente: «lee el CRUD de < | + | * Añade a '' |
| - | * Revisa las dos: quita lo que sea casualidad y no convención. Comprueba | + | * Escribe en '' |
| - | * ''/ | + | * ''/ |
| ==== Ejercicio 4 ==== | ==== Ejercicio 4 ==== | ||
| - | * Añade a '' | + | * Escribe |
| - | * ''/ | + | * Amplía |
| - | * Mira '' | + | * Finaliza el issue. |
| + | |||
| + | ==== Ejercicio 5 ==== | ||
| + | * Crea dos issues cualesquiera, | ||
| + | * Cambia los datos de prueba | ||
| + | * Finaliza los dos y comprueba con '' | ||
clase/daw/daw-proyecto/tema04.1791932774.txt.gz · Última modificación: por claude
