Tutorial

Generare diagrammi di architettura

Usa IBM Bob per analizzare la codebase di Galaxium Travels e generare diagrammi di classi UML Mermaid, diagrammi di sequenza e diagrammi dei casi d'uso. Impara a usare le menzioni di contesto in modalità Ask per esplorare il codice e la modalità Agent per salvare i risultati nel tuo repository.

I diagrammi di architettura ti danno un linguaggio visivo condiviso per una codebase prima di modificarla. In questo tutorial, usi Bob per leggere i file sorgente di Galaxium Travels e generare tre tipi di diagrammi UML: un diagramma di classi UML, un diagramma di sequenza e un diagramma dei casi d'uso. Usi la modalità Ask per esplorare il codice in sicurezza e generare il markup del diagramma, che usa Mermaid. Poi passi alla modalità Agent per salvare i diagrammi nel progetto.

GitHub fornisce supporto nativo per i diagrammi Mermaid nei file Markdown, quindi puoi salvare i diagrammi generati come file .md e visualizzarli renderizzati su GitHub.

In questo tutorial, l'output di Bob può differire dagli esempi a seconda dello stato attuale della codebase. Usa il markup generato come punto di partenza e perfezionalo secondo necessità.

Funzionalità chiave che imparerai

  • Menzioni di contesto: Fai riferimento a file e cartelle specifici nei tuoi prompt usando il simbolo @. Le menzioni di contesto permettono a Bob di sapere esattamente quali file analizzare per generare diagrammi accurati.
  • Modalità Ask: Leggi e analizza il codice senza che Bob apporti modifiche ai tuoi file.
  • Modalità Agent: Lascia che Bob scriva file in modo autonomo per persistere gli artefatti generati nel tuo progetto.

Prerequisiti

Per completare questo tutorial, hai bisogno di quanto segue:

  • Bob IDE installato.
  • Git installato localmente in modo da poter clonare il repository di esempio Galaxium Travels.
  • Familiarità con le basi dell'uso di Bob. Se sei nuovo a Bob, inizia con il tutorial di avvio rapido.

Configura il tuo workspace

Clona il repository Galaxium Travels

Nel tuo terminale, esegui il seguente comando per clonare il repository di esempio Galaxium Travels:

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

Avvia IBM Bob

Avvia l'IDE IBM Bob sul tuo computer.

Apri il progetto di esempio

Nell'IDE Bob, apri la cartella galaxium-travels che hai clonato. Se Bob chiede "Ti fidi degli autori dei file nella cartella?", fai clic su Sì, mi fido degli autori.

Esamina il file README.md nella directory radice per ottenere una panoramica dell'applicazione e della sua architettura. L'app Galaxium Travels simula un sistema di prenotazione voli con un frontend React, un backend Python FastAPI e un servizio di blocco inventario Java. La codebase è intenzionalmente complessa e rappresentativa di applicazioni del mondo reale, rendendola un'ottima candidata per generare diagrammi di architettura.

Apri l'interfaccia chat di Bob

Se l'interfaccia chat non è già aperta, fai clic sull'icona Bob nella barra di navigazione o usa la scorciatoia Option + Command + B (Mac) o Ctrl + Alt + B (Windows).

Inizializza il contesto del progetto

Bob parte in modalità Agent per impostazione predefinita. Se hai cambiato modalità, assicurati di passare alla modalità Agent prima di eseguire il comando di inizializzazione. Bob deve scrivere file per configurare il contesto del progetto.

Inserisci il comando /init nel campo di input dell'interfaccia chat. Se hai l'approvazione automatica disabilitata, Bob ti chiederà il permesso di leggere i file e scrivere i file AGENTS.md.

 /init

Bob legge i file rilevanti nel progetto. Bob quindi genera il file principale AGENTS.md nella directory radice. Bob crea anche una cartella .bob che contiene un AGENTS.md per ogni modalità.

Esamina i file AGENTS.md generati per capire come Bob ha configurato il contesto del progetto e quali capacità ha Bob in ogni modalità.

Passa alla modalità Ask

Seleziona Ask nel selettore di modalità sotto il campo di input della chat. Puoi anche digitare /ask nel campo di input della chat per cambiare modalità.

A differenza della modalità Agent, la modalità Ask è di sola lettura. Bob può leggere e analizzare i file ma non può creare o modificare nulla, rendendola sicura per l'esplorazione del codice.

Genera un diagramma di classi UML

Un diagramma di classi UML mappa il modello di dati di un'applicazione: le entità (classi), i loro attributi e le relazioni tra di esse. Per Galaxium Travels, questo copre i modelli Python SQLAlchemy nel backend e le classi di dominio Java nel servizio di blocco inventario.

Crea un prompt per analizzare i modelli di dati in entrambi i servizi e produrre un classDiagram Mermaid. Usa le menzioni di contesto per specificare i file rilevanti per Bob da analizzare. Per impostazione predefinita, Bob genera il diagramma Mermaid come immagine renderizzata. Per esaminare il markup Mermaid grezzo invece, aggiungi l'istruzione "Genera solo il blocco di codice Mermaid. Non renderizzare il diagramma Mermaid." al tuo prompt.

In modalità Ask, inserisci il seguente prompt nel campo di input della chat:

Analizza i modelli di dati in @booking_system_backend/models.py e le 
classi di dominio Java in @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/domain.

Genera un classDiagram Mermaid che mostri tutte le classi, i loro attributi,
i loro metodi (se presenti) e le relazioni tra di esse. 
Includi l'enum BookingStatus.

Genera il markup Mermaid. Non renderizzare il diagramma Mermaid.

Bob legge entrambi i file e produce markup del diagramma simile al seguente:

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 diagramma di sequenza

Un diagramma di sequenza mostra come i componenti interagiscono a runtime in un flusso specifico, ordinato per tempo. Il flusso di prenotazione Galaxium Travels si estende sul frontend React, il backend Python FastAPI e il servizio di blocco inventario Java.

Crea un prompt per tracciare il flusso di prenotazione completo e produrre un sequenceDiagram Mermaid. Usa le menzioni di contesto per specificare i file rilevanti per Bob da analizzare. Più sei specifico nel tuo prompt su quali file analizzare e quale flusso vuoi diagrammare, più accurato è l'output.

In modalità Ask, inserisci il seguente prompt nel campo di input della chat:

Analizza il flusso di prenotazione in @booking_system_frontend/src/services,
@booking_system_backend/server.py, @booking_system_backend/services/booking.py,
e @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/api.

Genera un sequenceDiagram Mermaid che mostri il flusso completo per un
utente che prenota un volo, inclusi i passaggi di preventivo e blocco con il servizio Java.

Genera il markup Mermaid. Non renderizzare il diagramma Mermaid.

Bob traccia la catena di interazione e produce markup del diagramma simile al seguente:

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 diagramma dei casi d'uso

Un diagramma dei casi d'uso identifica gli attori in un sistema e le capacità che ogni attore può esercitare. Mermaid non ha un tipo di diagramma dei casi d'uso nativo, quindi rappresenti questo con un flowchart LR che raggruppa i casi d'uso per attore.

Crea un prompt per identificare tutti gli attori e i loro casi d'uso nell'intera applicazione. Gli attori includono tipi di utenti e sistemi esterni. Usa le menzioni di contesto per specificare i file rilevanti per Bob da analizzare, incluse le pagine frontend, gli endpoint REST backend e gli strumenti MCP. Più sei specifico nel tuo prompt su quali file analizzare, più accurato è l'output. Inoltre, istruisci Bob a fare l'escape delle parentesi graffe nel markup Mermaid in modo che il renderer Mermaid non tenti di interpretare le parentesi graffe come sintassi di template.

In modalità Ask, inserisci il seguente prompt nel campo di input della chat:

Analizza l'applicazione completa Galaxium Travels. 

Identifica tutti gli attori (tipi di utenti o sistemi esterni) e i casi d'uso che ogni
attore può eseguire, in base alle pagine frontend, agli endpoint REST backend
e agli strumenti MCP.

Genera un flowchart LR Mermaid che rappresenti questo come un diagramma dei casi d'uso,
raggruppando i casi d'uso sotto i rispettivi attori usando i sottografi.

Fai l'escape delle parentesi graffe nel markup Mermaid in modo che il renderer Mermaid non
tenti di interpretare le parentesi graffe come sintassi di template.

Genera il markup Mermaid. Non renderizzare il diagramma Mermaid.

Bob analizza l'applicazione e produce markup del diagramma simile al seguente:

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

Salva i diagrammi nel repository

Passa Bob alla modalità Agent e chiedigli di salvare i diagrammi che hai generato nel repository. Ogni diagramma viene salvato come file Markdown in una nuova cartella docs/architecture/.

Passa alla modalità Agent

Seleziona Agent nel selettore di modalità, o digita /agent nel campo di input della chat.

Salva tutti e tre i diagrammi

Chiedi a Bob di creare i file di documentazione dell'architettura.

Crea una cartella docs/architecture/ nella radice del repository.

Salva ciascuno dei tre diagrammi che abbiamo generato come file Markdown individuali:
- class-diagram.md — il diagramma di classi UML
- sequence-diagram.md — il diagramma di sequenza del flusso di prenotazione
- use-case-diagram.md — il diagramma di flusso dei casi d'uso

Ogni file dovrebbe avere un breve titolo, il blocco di codice Mermaid che abbiamo
generato e una breve descrizione del diagramma.

Bob crea i tre file. Fai clic su Approve e Save per ogni file che Bob scrive.

Verifica l'output

Apri ogni file nell'esploratore file di Bob per confermare che i blocchi di codice Mermaid delimitati siano presenti. Hai queste opzioni per verificare i diagrammi:

  • Chiedi a Bob di mostrarti un'anteprima del file Markdown.

    Nel campo di input della chat, inserisci il seguente prompt:

      Mostrami un'anteprima di docs/architecture/class-diagram.md

    Bob renderizza il file Markdown, incluso il diagramma Mermaid, nell'interfaccia chat. Fai clic sul diagramma renderizzato per aprirlo in una vista più grande.

    Puoi farlo per ciascuno dei tre file per vedere tutti i diagrammi renderizzati.

  • Incolla il markup del diagramma in Mermaid Live Editor per visualizzare in anteprima il diagramma renderizzato.

  • Esegui il commit e il push delle modifiche in un repository GitHub. Quindi visualizza i file su GitHub per vedere i diagrammi renderizzati.

Risoluzione dei problemi

Bob genera markup Mermaid che non compila

Il parser di Mermaid è rigoroso. Anche un singolo carattere non valido, una parola chiave non supportata o un'interruzione di riga mancante può causare il fallimento silenzioso di un diagramma o generare un errore di parsing. Usa il seguente approccio per diagnosticare e risolvere il problema.

Identifica la riga che fallisce

Quando Bob produce un errore di parsing, l'output include il numero di riga e uno snippet del codice problematico.

Se Bob non genera un errore di parser, incolla il markup in Mermaid Live Editor. L'editor evidenzia la riga problematica e mostra l'errore di parser, che può aiutarti a identificare il problema.

Puoi anche ispezionare visivamente il markup per problemi comuni come caratteri speciali non escaped nelle etichette, sottografi non chiusi o errori di sintassi nelle frecce.

SintomoCausa probabileSoluzione
Errore di parsing vicino a { o }Parentesi graffe non escaped nelle etichette dei nodi flowchart o classDiagramSostituisci { con &#123; e } con &#125;, o riformula l'etichetta
Errore di parsing vicino a ( o )Parentesi in un ID nodoRacchiudi l'etichetta tra virgolette: A["label (note)"]
Errore end o subgraph inaspettatoSottografo non chiusoAssicurati che ogni blocco subgraph abbia un end corrispondente
Tipo di freccia non riconosciutoSintassi della freccia errata per il tipo di diagramma--> è per flowchart; classDiagram usa -->, ..>, --|> ecc.; sequenceDiagram usa ->>, -->>
Nodo definito ma non connessoIl nodo orfano non causa errori ma può confondere alcuni rendererConnetti il nodo o rimuovilo
Il diagramma si renderizza parzialmente poi si fermaL'etichetta contiene un carattere " nudoFai l'escape delle virgolette all'interno delle etichette: A["it\'s a label"]

Chiedi a Bob di risolvere il problema

Dai a Bob l'errore di parser e la riga che fallisce. Quindi chiedi a Bob di correggere righe specifiche.

Ad esempio:

Il classDiagram Mermaid non riesce a fare il parsing con questo errore:
Parse error on line 42: ...unexpected token 'NEWLINE'

Ecco il blocco rilevante:
    Booking ..> BookingStatus : status (active)

Correggi la sintassi in modo che compili senza cambiare la struttura del diagramma.

Bob può mirare a una correzione mirata senza rigenerare contenuti che hai già esaminato.

Chiedi a Bob di validare prima di generare

Se stai rigenerando un diagramma da zero, aggiungi un'istruzione di validazione esplicita al prompt:

Prima di generare il blocco Mermaid, analizzalo mentalmente e conferma che ogni ID nodo
sia valido, ogni sottografo sia chiuso e tutti i caratteri speciali nelle etichette siano escaped.

Riduci l'ambito quando il diagramma è grande

Se un diagramma con molti nodi continua a produrre markup non valido, chiedi a Bob di generarlo in sezioni, come prima i modelli Python e poi i modelli Java. Successivamente, chiedi a Bob di assemblare i blocchi. Le generazioni più piccole sono più facili per Bob da validare e più facili per te da confrontare.

Prossimi passi

In questo tutorial, hai usato le menzioni di contesto e la modalità Ask per esplorare la codebase Galaxium Travels e generare tre tipi di diagrammi di architettura con Bob, poi hai usato la modalità Agent per salvarli nel repository. Continua con le seguenti risorse:

Come valuti questo argomento?