Tutoriales

Generar diagramas de arquitectura

Usa IBM Bob para analizar la base de código de Galaxium Travels y generar diagramas de clases UML de Mermaid, diagramas de secuencia y diagramas de casos de uso. Aprende a usar menciones de contexto en el modo Ask para explorar código y el modo Agent para guardar los resultados en tu repositorio.

Los diagramas de arquitectura te dan un lenguaje visual compartido para una base de código antes de modificarla. En este tutorial, usas Bob para leer los archivos fuente de Galaxium Travels y generar tres tipos de diagramas UML: un diagrama de clases UML, un diagrama de secuencia y un diagrama de casos de uso. Usas el modo Ask para explorar el código de forma segura y generar el markup del diagrama, que usa Mermaid. Luego cambias al modo Agent para guardar los diagramas en el proyecto.

GitHub proporciona soporte nativo para diagramas Mermaid en archivos Markdown, por lo que puedes guardar los diagramas generados como archivos .md y verlos renderizados en GitHub.

En este tutorial, la salida de Bob puede diferir de los ejemplos dependiendo del estado actual de la base de código. Usa el markup generado como punto de partida y refínalo según sea necesario.

Características clave que aprenderás

  • Menciones de contexto: Referencia archivos y carpetas específicos en tus prompts usando el símbolo @. Las menciones de contexto permiten que Bob sepa exactamente qué archivos analizar para generar diagramas precisos.
  • Modo Ask: Lee y analiza código sin que Bob haga cambios en tus archivos.
  • Modo Agent: Permite que Bob escriba archivos de forma autónoma para persistir artefactos generados en tu proyecto.

Requisitos previos

Para completar este tutorial, necesitas lo siguiente:

  • Bob IDE instalado.
  • Git instalado localmente para que puedas clonar el repositorio de ejemplo de Galaxium Travels.
  • Familiaridad con los conceptos básicos del uso de Bob. Si eres nuevo en Bob, comienza con el tutorial de inicio rápido.

Configura tu espacio de trabajo

Clona el repositorio de Galaxium Travels

En tu terminal, ejecuta el siguiente comando para clonar el repositorio de ejemplo de Galaxium Travels:

git clone https://github.com/ibm/galaxium-travels.git

Inicia IBM Bob

Inicia el IDE de IBM Bob en tu computadora.

Abre el proyecto de ejemplo

En el IDE de Bob, abre la carpeta galaxium-travels que clonaste. Si Bob pregunta "¿Confías en los autores de los archivos en la carpeta?", haz clic en Sí, confío en los autores.

Revisa el archivo README.md en el directorio raíz para obtener una descripción general de la aplicación y su arquitectura. La aplicación Galaxium Travels simula un sistema de reserva de vuelos con un frontend de React, un backend de Python FastAPI y un servicio de retención de inventario de Java. La base de código es intencionalmente compleja y representativa de aplicaciones del mundo real, lo que la convierte en una excelente candidata para generar diagramas de arquitectura.

Abre la interfaz de chat de Bob

Si la interfaz de chat no está abierta, haz clic en el icono de Bob en la barra de navegación o usa el atajo Option + Command + B (Mac) o Ctrl + Alt + B (Windows).

Inicializa el contexto del proyecto

Bob inicia en modo Agent por defecto. Si has cambiado de modo, asegúrate de cambiar al modo Agent antes de ejecutar el comando de inicialización. Bob necesita escribir archivos para configurar el contexto del proyecto.

Ingresa el comando /init en el campo de entrada de la interfaz de chat. Si tienes la aprobación automática deshabilitada, Bob te pedirá permiso para leer archivos y escribir los archivos AGENTS.md.

 /init

Bob lee los archivos relevantes en el proyecto. Bob luego genera el archivo principal AGENTS.md en el directorio raíz. Bob también crea una carpeta .bob que contiene un AGENTS.md para cada modo.

Revisa los archivos AGENTS.md generados para entender cómo Bob ha configurado el contexto del proyecto y qué capacidades tiene Bob en cada modo.

Cambia al modo Ask

Selecciona Ask en el selector de modo debajo del campo de entrada de chat. También puedes escribir /ask en el campo de entrada de chat para cambiar de modo.

A diferencia del modo Agent, el modo Ask es de solo lectura. Bob puede leer y analizar archivos pero no puede crear ni modificar nada, lo que lo hace seguro para la exploración de código.

Genera un diagrama de clases UML

Un diagrama de clases UML mapea el modelo de datos de una aplicación: las entidades (clases), sus atributos y las relaciones entre ellas. Para Galaxium Travels, esto cubre los modelos de Python SQLAlchemy en el backend y las clases de dominio de Java en el servicio de retención de inventario.

Crea un prompt para analizar los modelos de datos en ambos servicios y producir un classDiagram de Mermaid. Usa menciones de contexto para especificar los archivos relevantes para que Bob los analice. Por defecto, Bob genera el diagrama Mermaid como una imagen renderizada. Para revisar el markup de Mermaid sin procesar, agrega la instrucción "Genera solo el bloque de código Mermaid. No renderices el diagrama Mermaid." a tu prompt.

En el modo Ask, ingresa el siguiente prompt en el campo de entrada de chat:

Analiza los modelos de datos en @booking_system_backend/models.py y las 
clases de dominio de Java en @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/domain.

Genera un classDiagram de Mermaid que muestre todas las clases, sus atributos,
sus métodos (si los hay) y las relaciones entre ellas. 
Incluye el enum BookingStatus.

Genera el markup de Mermaid. No renderices el diagrama Mermaid.

Bob lee ambos archivos y produce markup de diagrama similar al siguiente:

classDiagram
    direction LR

    %% ── Python / SQLAlchemy (booking_system_backend/models.py) ──────────

    class User {
        +int user_id PK
        +str name
        +str email
    }

    class Flight {
        +int flight_id PK
        +str origin
        +str destination
        +str departure_time
        +str arrival_time
        +int base_price
        +int economy_seats_available
        +int business_seats_available
        +int galaxium_seats_available
    }

    class Booking {
        +int booking_id PK
        +int user_id FK
        +int flight_id FK
        +str status
        +str booking_time
        +str seat_class
        +int price_paid
    }

    class BookingStatus {
        <<enumeration>>
        BOOKED = "booked"
        CANCELLED = "cancelled"
        CANCELED = "cancelled"
        COMPLETED = "completed"
    }

    %% ── Java / JPA (holdservice/domain) ────────────────────────────────

    class Quote {
        +String quoteId PK
        +Integer flightId
        +String seatClass
        +Integer quantity
        +Integer travelerId
        +String travelerName
        +Long pricePerSeat
        +Long totalPrice
        +Instant expiresAt
        +QuoteStatus status
        +Instant createdAt
        #onCreate() void
    }

    class QuoteStatus {
        <<enumeration>>
        CREATED
    }

    class Hold {
        +String holdId PK
        +String quoteId FK
        +HoldStatus status
        +Instant reservedUntil
        +String externalBookingReference
        +String errorMessage
        +Instant createdAt
        +Instant updatedAt
        #onCreate() void
        #onUpdate() void
    }

    class HoldStatus {
        <<enumeration>>
        HELD
        EXPIRED
        CONFIRMED
        RELEASED
        CONFIRMATION_FAILED
    }

    class AuditEvent {
        +String eventId PK
        +String entityType
        +String entityId
        +String eventType
        +String details
        +Instant createdAt
        #onCreate() void
    }

    %% ── Relationships ───────────────────────────────────────────────────

    User        "1" --> "0..*" Booking      : places
    Flight      "1" --> "0..*" Booking      : booked on
    Booking          ..>        BookingStatus : status

    Quote       "1" --> "0..*" Hold         : generates
    Quote            ..>        QuoteStatus  : status
    Hold             ..>        HoldStatus   : status

    AuditEvent       ..>        Quote        : references entityId
    AuditEvent       ..>        Hold         : references entityId

Genera un diagrama de secuencia

Un diagrama de secuencia muestra cómo los componentes interactúan en tiempo de ejecución en un flujo específico, ordenado por tiempo. El flujo de reserva de Galaxium Travels abarca el frontend de React, el backend de Python FastAPI y el servicio de retención de inventario de Java.

Crea un prompt para rastrear el flujo completo de reserva y producir un sequenceDiagram de Mermaid. Usa menciones de contexto para especificar los archivos relevantes para que Bob los analice. Cuanto más específico seas en tu prompt sobre qué archivos analizar y qué flujo quieres diagramar, más precisa será la salida.

En el modo Ask, ingresa el siguiente prompt en el campo de entrada de chat:

Analiza el flujo de reserva en @booking_system_frontend/src/services,
@booking_system_backend/server.py, @booking_system_backend/services/booking.py,
y @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/api.

Genera un sequenceDiagram de Mermaid que muestre el flujo completo para un
usuario que reserva un vuelo, incluyendo los pasos de cotización y retención con el servicio de Java.

Genera el markup de Mermaid. No renderices el diagrama Mermaid.

Bob rastrea la cadena de interacción y produce markup de diagrama similar al siguiente:

sequenceDiagram
    autonumber
    participant U  as User (Browser)
    participant FE as Frontend<br/>(api.ts)
    participant PY as Python Backend<br/>(server.py)
    participant BS as BookingService<br/>(booking.py)
    participant QC as QuoteController<br/>(Java)
    participant QS as QuoteService<br/>(Java)
    participant HC as HoldController<br/>(Java)
    participant HS as HoldService<br/>(Java)
    participant DB as Python SQLite
    participant JDB as Java SQLite

    Note over U,JDB: ── Phase 1: Create Quote ──────────────────────────────────

    U->>FE: createQuote({ flightId, seatClass,<br/>quantity, travelerId, travelerName })
    FE->>PY: POST /quotes
    PY->>QC: POST /api/v1/quotes
    QC->>QS: createQuote(request)
    QS->>QS: generateQuoteId() → "Q-2025-000001"
    QS->>QS: pricingService.calculatePrice(flightId, seatClass)
    QS->>JDB: save Quote (status=CREATED, expiresAt=+24h)
    QS->>JDB: save AuditEvent (QUOTE / CREATED)
    QC-->>PY: 201 Quote
    Note right of PY: Returns {"error":"..."} HTTP 200<br/>if Java service unreachable
    PY-->>FE: Quote JSON
    FE->>FE: assertNotProxyError(response.data)
    FE-->>U: quoteId

    Note over U,JDB: ── Phase 2: Create Hold ───────────────────────────────────

    U->>FE: createHold(quoteId)
    FE->>PY: POST /quotes/{quoteId}/holds
    PY->>HC: POST /api/v1/quotes/{quoteId}/holds
    HC->>HS: createHold(quoteId)
    HS->>JDB: findById(quoteId)
    JDB-->>HS: Quote
    HS->>HS: check quote not expired
    HS->>HS: generateHoldId() → "H-2025-000001"
    HS->>JDB: save Hold (status=HELD,<br/>reservedUntil=+15min)
    HS->>JDB: save AuditEvent (HOLD / CREATED)
    HC-->>PY: 201 Hold
    PY-->>FE: Hold JSON
    FE->>FE: assertNotProxyError(response.data)
    FE-->>U: holdId

    Note over U,JDB: ── Phase 3: Confirm Hold → Create Booking ─────────────────

    U->>FE: confirmHold(holdId)
    FE->>PY: POST /holds/{holdId}/confirm
    PY->>HC: POST /api/v1/holds/{holdId}/confirm
    HC->>HS: confirmHold(holdId)
    HS->>JDB: findById(holdId)
    JDB-->>HS: Hold
    HS->>HS: check status == HELD
    HS->>HS: check reservedUntil not passed
    HS->>JDB: findById(hold.quoteId)
    JDB-->>HS: Quote

    HS->>PY: POST /internal/bookings/from-hold<br/>{ travelerId, travelerName, flightId, seatClass }
    PY->>BS: book_flight(db, user_id, name,<br/>flight_id, seat_class)
    BS->>DB: query Flight (check seats available)
    BS->>DB: query User (validate user_id + name match)
    BS->>DB: decrement {seat_class}_seats_available
    BS->>DB: insert Booking (status="booked")
    DB-->>BS: Booking row
    BS-->>PY: BookingOut

    alt booking succeeded
        PY-->>HS: 200 { booking_id, ... }
        HS->>JDB: update Hold (status=CONFIRMED,<br/>externalBookingReference=booking_id)
        HS->>JDB: save AuditEvent (HOLD / CONFIRMED)
        HC-->>PY: 200 Hold (CONFIRMED)
        PY-->>FE: Hold JSON
        FE->>FE: assertNotProxyError(response.data)
        FE-->>U: Booking confirmed ✓
    else booking failed (name mismatch / no seats / user not found)
        PY-->>HS: 400 { error, error_code, details }
        HS->>JDB: update Hold (status=CONFIRMATION_FAILED,<br/>errorMessage=...)
        HS->>JDB: save AuditEvent (HOLD / CONFIRMATION_FAILED)
        HC-->>PY: 400 Bad Request
        PY-->>FE: error response
        FE-->>U: Error shown to user ✗
    end

Genera un diagrama de casos de uso

Un diagrama de casos de uso identifica los actores en un sistema y las capacidades que cada actor puede ejercer. Mermaid no tiene un tipo de diagrama de casos de uso nativo, por lo que representas esto con un flowchart LR que agrupa casos de uso por actor.

Crea un prompt para identificar todos los actores y sus casos de uso en toda la aplicación. Los actores incluyen tipos de usuarios y sistemas externos. Usa menciones de contexto para especificar los archivos relevantes para que Bob los analice, incluyendo las páginas del frontend, endpoints REST del backend y herramientas MCP. Cuanto más específico seas en tu prompt sobre qué archivos analizar, más precisa será la salida. Además, instruye a Bob para que escape las llaves en el markup de Mermaid para que el renderizador de Mermaid no intente interpretar las llaves como sintaxis de plantilla.

En el modo Ask, ingresa el siguiente prompt en el campo de entrada de chat:

Analiza la aplicación completa de Galaxium Travels. 

Identifica todos los actores (tipos de usuarios o sistemas externos) y los casos de uso que cada
actor puede realizar, basándose en las páginas del frontend, endpoints REST del backend
y herramientas MCP.

Genera un flowchart LR de Mermaid que represente esto como un diagrama de casos de uso,
agrupando casos de uso bajo sus respectivos actores usando subgrafos.

Escapa las llaves en el markup de Mermaid para que el renderizador de Mermaid no
intente interpretar las llaves como sintaxis de plantilla.

Genera el markup de Mermaid. No renderices el diagrama Mermaid.

Bob analiza la aplicación y produce markup de diagrama similar al siguiente:

flowchart LR

    subgraph Traveller["👤 Traveller (Browser)"]
        T1[Browse available flights]
        T2[Search flights by origin / destination]
        T3[Filter flights by date, price, seat class,\nduration, route category, time period]
        T4[Register account]
        T5[Sign in with name and email]
        T6[Select seat class\neconomy / business / galaxium]
        T7[Get price quote]
        T8[Place seat hold - 15-minute timer]
        T9[Confirm hold and create booking]
        T10[Release hold]
        T11[View active bookings]
        T12[View past bookings]
        T13[Cancel booking]
        T14[View pending holds with countdown]
        T15[Dismiss expired hold]
    end

    subgraph AIAgent["🤖 AI Agent (MCP Client)"]
        A1[list_flights]
        A2[register_user]
        A3[get_user_id]
        A4[book_flight]
        A5[get_bookings]
        A6[cancel_booking]
    end

    subgraph JavaService["☕ Java Hold Service\n(Internal System)"]
        J1[Confirm hold via POST /internal/bookings/from-hold]
        J2[Auto-expire holds after timeout]
    end

    subgraph RestAPI["🐍 Python REST API\n(External Consumers / Swagger)"]
        R1[GET  /flights — list and filter flights]
        R2[POST /register — register user]
        R3[GET  /user — look up user by name and email]
        R4[POST /book — book a flight]
        R5[GET  /bookings/&#123;user_id&#125; — get user bookings]
        R6[POST /cancel/&#123;booking_id&#125; — cancel booking]
        R7[POST /quotes — create quote proxy]
        R8[GET  /quotes/&#123;id&#125; — get quote proxy]
        R9[POST /quotes/&#123;id&#125;/holds — create hold proxy]
        R10[GET  /holds/&#123;id&#125; — get hold proxy]
        R11[POST /holds/&#123;id&#125;/confirm — confirm hold proxy]
        R12[POST /holds/&#123;id&#125;/release — release hold proxy]
        R13[GET  / — health check]
    end

    Traveller   -->|uses frontend which calls| RestAPI
    AIAgent     -->|MCP over HTTP at /mcp| RestAPI
    JavaService -->|calls back via internal endpoint| RestAPI

Guarda los diagramas en el repositorio

Cambia Bob al modo Agent y pídele que guarde los diagramas que generaste en el repositorio. Cada diagrama se guarda como un archivo Markdown en una nueva carpeta docs/architecture/.

Cambia al modo Agent

Selecciona Agent en el selector de modo, o escribe /agent en el campo de entrada de chat.

Guarda los tres diagramas

Pide a Bob que cree los archivos de documentación de arquitectura.

Crea una carpeta docs/architecture/ en la raíz del repositorio.

Guarda cada uno de los tres diagramas que generamos como archivos Markdown individuales:
- class-diagram.md — el diagrama de clases UML
- sequence-diagram.md — el diagrama de secuencia del flujo de reserva
- use-case-diagram.md — el diagrama de flujo de casos de uso

Cada archivo debe tener un encabezado de título corto, el bloque de código Mermaid que
generamos y una breve descripción del diagrama.

Bob crea los tres archivos. Haz clic en Approve y Save para cada archivo que Bob escribe.

Verifica la salida

Abre cada archivo en el explorador de archivos de Bob para confirmar que los bloques de código Mermaid delimitados están presentes. Tienes estas opciones para verificar los diagramas:

  • Pide a Bob que te muestre una vista previa del archivo Markdown.

    En el campo de entrada de chat, ingresa el siguiente prompt:

      Muéstrame una vista previa de docs/architecture/class-diagram.md

    Bob renderiza el archivo Markdown, incluido el diagrama Mermaid, en la interfaz de chat. Haz clic en el diagrama renderizado para abrirlo en una vista más grande.

    Puedes hacer esto para cada uno de los tres archivos para ver todos los diagramas renderizados.

  • Pega el markup del diagrama en Mermaid Live Editor para previsualizar el diagrama renderizado.

  • Confirma y envía los cambios a un repositorio de GitHub. Luego visualiza los archivos en GitHub para ver los diagramas renderizados.

Solución de problemas

Bob genera markup de Mermaid que no compila

El parser de Mermaid es estricto. Incluso un solo carácter inválido, una palabra clave no soportada o un salto de línea faltante puede hacer que un diagrama falle silenciosamente o genere un error de análisis. Usa el siguiente enfoque para diagnosticar y solucionar el problema.

Identifica la línea que falla

Cuando Bob produce un error de análisis, la salida incluye el número de línea y un fragmento del código problemático.

Si Bob no genera un error de parser, pega el markup en Mermaid Live Editor. El editor resalta la línea problemática y muestra el error de parser, lo que puede ayudarte a identificar el problema.

También puedes inspeccionar visualmente el markup en busca de problemas comunes como caracteres especiales sin escapar en etiquetas, subgrafos sin cerrar o errores de sintaxis en flechas.

SíntomaCausa probableSolución
Error de análisis cerca de { o }Llaves sin escapar en etiquetas de nodos de flowchart o classDiagramReemplaza { con &#123; y } con &#125;, o reformula la etiqueta
Error de análisis cerca de ( o )Paréntesis en un ID de nodoEnvuelve la etiqueta entre comillas: A["label (note)"]
Error inesperado de end o subgraphSubgrafo no cerradoAsegúrate de que cada bloque subgraph tenga un end correspondiente
Tipo de flecha no reconocidoSintaxis de flecha incorrecta para el tipo de diagrama--> es para flowchart; classDiagram usa -->, ..>, --|> etc.; sequenceDiagram usa ->>, -->>
Nodo definido pero no conectadoEl nodo huérfano no causa error pero puede confundir algunos renderizadoresConecta el nodo o elimínalo
El diagrama se renderiza parcialmente y luego se detieneLa etiqueta contiene un carácter " sin escaparEscapa las comillas dentro de las etiquetas: A["it\'s a label"]

Pide a Bob que solucione el problema

Dale a Bob el error de parser y la línea que falla. Luego pídele a Bob que corrija líneas específicas.

Por ejemplo:

El classDiagram de Mermaid no se puede analizar con este error:
Parse error on line 42: ...unexpected token 'NEWLINE'

Aquí está el bloque relevante:
    Booking ..> BookingStatus : status (active)

Corrige la sintaxis para que compile sin cambiar la estructura del diagrama.

Bob puede hacer una corrección específica sin regenerar contenido que ya revisaste.

Pide a Bob que valide antes de generar

Si estás regenerando un diagrama desde cero, agrega una instrucción de validación explícita al prompt:

Antes de generar el bloque Mermaid, analízalo mentalmente y confirma que cada ID de nodo
es válido, cada subgrafo está cerrado y todos los caracteres especiales en las etiquetas están escapados.

Reduce el alcance cuando el diagrama es grande

Si un diagrama con muchos nodos sigue produciendo markup inválido, pide a Bob que lo genere en secciones, como primero los modelos de Python y luego los modelos de Java. Después, pide a Bob que ensamble los bloques. Las generaciones más pequeñas son más fáciles para que Bob las valide y más fáciles para que tú las compares.

Próximos pasos

En este tutorial, usaste menciones de contexto y el modo Ask para explorar la base de código de Galaxium Travels y generar tres tipos de diagramas de arquitectura con Bob, luego usaste el modo Agent para guardarlos en el repositorio. Continúa con los siguientes recursos:

¿Cómo es este tema?