Diagramma di Componenti C4: guida completa con esempi - Archyl Blog

Il diagramma di componenti C4 (livello 3 del modello C4) zooma in un singolo container e mostra i componenti al suo interno. Questa guida spiega cos'è un diagramma di componenti, quando vale la pena mantenerlo, un esempio completo svolto, gli errori comuni e come mantenere accurato il livello 3 senza l'onere della manutenzione.

Diagramma di Componenti C4: guida completa con esempi

Il diagramma di componenti è il livello 3 del modello C4 -- ed è il livello con la peggiore reputazione. Il livello 1 (Contesto di Sistema) è facile da disegnare e cambia raramente. Il livello 2 (Container) si mappa in modo pulito su ciò che distribuisci. Ma il livello 3? Zooma negli interni di un singolo container, il che significa che cambia ogni volta che uno sviluppatore ristruttura un package. La maggior parte dei team o lo salta del tutto, oppure lo disegna una volta e lo lascia marcire.

Ed è un peccato, perché un diagramma di componenti ben mantenuto è il singolo artefatto più utile per uno sviluppatore che entra in un codebase. Risponde alla domanda che ogni nuovo arrivato si pone: "dove vive davvero la logica per X?"

Questa guida copre cos'è un diagramma di componenti C4, come differisce da un diagramma di componenti UML, quando il livello 3 vale il costo di manutenzione (e quando no), un esempio completo svolto, gli errori che rendono inutili i diagrammi di componenti e come mantenerli accurati senza farlo tutto a mano.

Se sei nuovo al modello C4 in sé, inizia dalla nostra guida completa al modello C4, poi torna qui.

Che cos'è un diagramma di componenti C4?

Un diagramma di componenti apre un container -- un'unità deployabile dal tuo diagramma di container -- e rivela i componenti al suo interno.

In termini C4, un componente è un raggruppamento coeso di funzionalità correlate che sta dietro un'interfaccia ben definita. Pensa ai principali blocchi costitutivi all'interno di un'applicazione:

  • Un controller HTTP o un gruppo di handler
  • Un domain service che possiede una porzione di logica di business
  • Un repository o uno strato di accesso ai dati
  • Un client che incapsula un'API esterna
  • Un middleware, un interceptor o un worker in background

La parola chiave è raggruppamento. Un componente è un'astrazione sul codice, non una singola classe o file. Il componente OrderService potrebbe estendersi su una dozzina di file, ma concettualmente è una cosa sola: la parte del container responsabile della logica di business degli ordini. Come recita la definizione del glossario, un componente C4 è "un raggruppamento di codice di livello più alto con una singola responsabilità" -- non una mappatura 1:1 a una classe di un linguaggio di programmazione.

A cosa risponde il diagramma di componenti

  • Come è strutturato internamente questo container?
  • Quale componente possiede quale responsabilità?
  • Come collaborano i componenti per gestire una richiesta?
  • Da dove originano le chiamate ai database e ai sistemi esterni?

Cosa lascia deliberatamente fuori

  • Singole classi, interfacce e funzioni (quello è il livello 4, il diagramma di codice)
  • Gli interni di altri container
  • Dettagli di deployment e infrastruttura

Un container per diagramma, solo componenti. Se ti ritrovi a disegnare classi, hai zoomato troppo.

Diagramma di componenti C4 vs. diagramma di componenti UML

Questo confonde le persone di continuo, perché anche UML ha qualcosa chiamato "diagramma di componenti" -- e non è la stessa cosa.

Un diagramma di componenti UML modella i componenti software come unità con interfacce fornite e richieste (la famosa notazione lollipop-and-socket), spesso enfatizzando il packaging fisico, gli artefatti e le relazioni di deployment. Viene con regole di notazione formali e un metamodello preciso.

Un diagramma di componenti C4 è più sciolto e più pragmatico. È semplicemente il livello 3 di una gerarchia di zoom: scatole per i componenti, frecce per le relazioni, una breve descrizione testuale su ciascuno. Non c'è alcuna notazione speciale da imparare. Il valore deriva dalla gerarchia -- ogni scatola di componente vive dentro uno specifico container, che vive dentro uno specifico sistema -- non dalla notazione in sé.

In pratica: se qualcuno chiede un "diagramma di componenti" in un contesto C4, vuole una mappa strutturale degli interni di un container che un nuovo sviluppatore possa leggere in due minuti. Se vuole interfacce lollipop e stereotipi <<artifact>>, sta chiedendo UML.

Quando vale la pena mantenere il livello 3?

Ecco la risposta onesta che la maggior parte delle guide salta: il livello 3 è il livello con il peggiore rapporto sforzo-stabilità in tutto il modello C4.

I diagrammi di contesto cambiano qualche volta all'anno. I diagrammi di container cambiano quando aggiungi o rimuovi un servizio -- forse mensilmente. I diagrammi di componenti cambiano ogni volta che qualcuno rifattorizza un package, estrae un servizio o rinomina un modulo. Se li mantieni a mano, ti stai iscrivendo a un giardinaggio costante, e nel momento in cui smetti, il diagramma inizia a mentire.

Quindi sii deliberato su dove spendi quello sforzo.

Crea un diagramma di componenti quando:

  • Il container è genuinamente complesso. Un'API backend con 15 package, più strati e confini non ovvi merita una mappa. Un servizio CRUD a tre endpoint no.
  • La struttura incarna un design deliberato. Se usi un'architettura esagonale, CQRS o uno schema di stratificazione pulito, il diagramma di componenti rende esplicita la struttura voluta -- e ti dà qualcosa da indicare quando una pull request la viola.
  • Più team toccano lo stesso container. Il codice condiviso ha bisogno di un modello mentale condiviso.
  • L'onboarding è un collo di bottiglia. Se i nuovi sviluppatori impiegano settimane per orientarsi in un container, un diagramma di componenti si ripaga con la prima assunzione.

Saltalo quando:

  • Il container è piccolo e la sua struttura di cartelle si spiega da sola.
  • Il container è di terze parti (non disegni gli interni di Redis).
  • Nessuno si impegnerà a tenerlo aggiornato. Un diagramma di componenti obsoleto è peggio di nessuno -- manda con sicurezza gli sviluppatori verso codice che non esiste più.

È esattamente per questo che il livello 3 è il livello che la maggior parte dei team o salta o automatizza. Generare i componenti dall'effettiva struttura del codice -- e verificarli contro di essa -- rimuove la tassa di manutenzione che uccide i diagrammi disegnati a mano. Più avanti ne parliamo.

Un esempio svolto: dentro un container API

Rendiamo la cosa concreta. Prendi la piattaforma e-commerce dalla nostra guida al modello C4 e zooma in un singolo container: la Order API (Go). Al livello 2 è una scatola. Al livello 3 si apre in componenti.

I componenti

Componente Responsabilità
Auth Middleware Valida i token JWT sulle richieste in entrata, inietta l'identità utente nel contesto della richiesta
Order Controller Endpoint REST per creare, leggere e cancellare ordini; validazione delle richieste e serializzazione delle risposte
Admin Controller Endpoint REST per la gestione back-office degli ordini (rimborsi, cambi di stato manuali)
Order Service Logica di business core: ciclo di vita dell'ordine, regole di prezzo, controlli di stock, orchestrazione dei pagamenti
Order Repository Strato di accesso ai dati; persiste e interroga gli ordini via SQL
Payment Client Incapsula l'API Stripe; gestisce autorizzazione, cattura e rimborsi
Email Adapter Invia email transazionali (conferma ordine, aggiornamenti di spedizione) via SendGrid
Event Publisher Pubblica eventi di dominio (OrderPlaced, OrderCancelled) su Kafka

Le relazioni

[Auth Middleware] --> [Order Controller] : Passes authenticated requests
[Auth Middleware] --> [Admin Controller] : Passes authenticated requests (admin role)
[Order Controller] --> [Order Service] : Delegates business operations
[Admin Controller] --> [Order Service] : Delegates back-office operations
[Order Service] --> [Order Repository] : Reads/writes orders
[Order Service] --> [Payment Client] : Authorizes and captures payments
[Order Service] --> [Email Adapter] : Triggers transactional emails
[Order Service] --> [Event Publisher] : Emits domain events
[Order Repository] --> [Order Database (PostgreSQL)] : SQL
[Payment Client] --> [Payment Gateway (Stripe)] : HTTPS/REST
[Email Adapter] --> [Email Service (SendGrid)] : HTTPS/REST
[Event Publisher] --> [Message Queue (Kafka)] : Publishes events

Nota che il database, Stripe, SendGrid e Kafka compaiono ai bordi. Non sono componenti di questo container -- sono container vicini e sistemi esterni -- ma mostrare da dove originano le chiamate in uscita è esattamente ciò che rende utile il diagramma.

Cosa dice questo diagramma a un nuovo sviluppatore

In trenta secondi, uno sviluppatore che entra in questo team apprende:

  1. Il percorso della richiesta: middleware → controller → service → repository. C'è esattamente un posto in cui vive la logica di business, e non è il controller.
  2. I confini: tutte le chiamate esterne passano per adapter dedicati (Payment Client, Email Adapter). Se devi parlare con Stripe, estendi il client; non importi l'SDK in un controller.
  3. Gli effetti collaterali: gli ordini producono eventi su Kafka ed email via SendGrid. Se un'email non viene inviata, sai quali due componenti controllare.
  4. Dove aggiungere codice: una nuova funzionalità "gift card" ha chiaramente bisogno di modifiche nel controller, nel service ed eventualmente di un nuovo client -- e il diagramma mostra il pattern da seguire.

Quest'ultimo punto è sottovalutato. Un diagramma di componenti non si limita a descrivere la struttura -- la prescrive. Dice ai contributori che aspetto ha "coerente con questo codebase".

Errori comuni con i diagrammi di componenti

Mappare una classe a un componente

L'errore più frequente. Se il tuo container ha 80 classi e il tuo diagramma di componenti ha 80 scatole, hai disegnato un diagramma di classi con passaggi in più. I componenti sono raggruppamenti: OrderController (un componente) potrebbe coprire cinque classi handler. Punta a 5-15 componenti per container. Se superi i 20, le tue astrazioni sono troppo a grana fine -- oppure il tuo container fa troppo.

Documentare ogni container al livello 3

La simmetria è allettante: "abbiamo 12 container, quindi ci servono 12 diagrammi di componenti." Resisti. La maggior parte di quei diagrammi non verrà mai letta e mai aggiornata. Documenta i due o tre container in cui la complessità fa davvero male, e lascia che la struttura delle cartelle parli per gli altri.

Lasciare marcire il diagramma

Il livello 3 va alla deriva più velocemente di qualsiasi altro livello. Un diagramma di componenti disegnato a gennaio descrive un container che probabilmente non esiste più a giugno. Ogni refactor, ogni package estratto, ogni modulo rinominato allarga il divario. E un diagramma sicuro di sé ma sbagliato è peggio di nessun diagramma: manda gli sviluppatori a caccia di componenti che sono stati cancellati due trimestri fa. Se non puoi automatizzare la manutenzione, almeno metti "aggiornare il diagramma di componenti" nella checklist delle pull request per quel container.

Disegnare componenti senza responsabilità

Una scatola etichettata OrderManager senza descrizione è rumore. Ogni componente dovrebbe portare un'affermazione di responsabilità in una riga ("Valida i token JWT e inietta l'identità utente"). Se non riesci a scrivere quella frase, il confine del componente è probabilmente sbagliato.

Mostrare dettaglio implementativo invece della struttura

Generics, design pattern, utility helper -- niente di tutto questo appartiene al livello 3. Se la parte interessante di un componente è come è implementato, quello è un lavoro per il diagramma di codice (o, più spesso, per il codice stesso).

Come Archyl mantiene accurati i diagrammi di componenti

Tutto quanto sopra porta alla stessa conclusione: i diagrammi di componenti sono preziosi, ma mantenerli a mano è una partita persa. È esattamente il problema che Archyl è stato costruito per risolvere.

La AI discovery estrae i componenti dal codice

Invece di disegnare i componenti a mano, colleghi il tuo repository ed esegui la AI discovery. Archyl analizza la struttura del tuo codice -- package, moduli, strati, convenzioni di denominazione -- e propone un modello C4, inclusi i componenti dentro ogni container e le relazioni tra di essi. Un servizio Go con package handlers/, service/ e repository/ torna esattamente come il tipo di diagramma di componenti mostrato nell'esempio sopra. Tu rivedi i suggerimenti, li accetti o li modifichi, e hai un modello di livello 3 in pochi minuti.

La drift detection segnala le divergenze

Questa è la parte che mantiene vivo il livello 3. Poiché Archyl collega i componenti a file e directory reali nel tuo repository, può controllare di continuo se i componenti documentati esistono ancora nel codice. Quando qualcuno cancella un package, rinomina un modulo o ristruttura uno strato, il punteggio di drift cala e i componenti interessati vengono segnalati. Il tuo diagramma di componenti smette di essere un'istantanea e diventa un contratto monitorato.

Architecture as Code

Se preferisci definizioni esplicite alla discovery, Archyl supporta la definizione del tuo modello C4 -- sistemi, container, componenti e relazioni -- in YAML che vive nel tuo repository. Il tuo diagramma di componenti è versionato, rivisto nelle pull request e generato automaticamente. Combinato con la drift detection, questo ti dà documentazione di livello 3 con le caratteristiche di manutenzione del codice.

FAQ

Qual è la differenza tra un diagramma di componenti C4 e un diagramma di componenti UML?

Un diagramma di componenti UML è una notazione formale con interfacce fornite/richieste, artefatti e stereotipi, focalizzata sulla modellazione dei componenti come unità impacchettate. Un diagramma di componenti C4 è il livello 3 della gerarchia di zoom C4: una vista pragmatica fatta di scatole e frecce dei componenti dentro uno specifico container. C4 non ha requisiti di notazione formale -- il suo valore deriva dalla gerarchia coerente (sistema → container → componente → codice), non dai simboli.

Un componente è la stessa cosa di una classe?

No. Un componente C4 è un raggruppamento coeso di codice dietro un'interfaccia ben definita -- può essere implementato come una classe, una dozzina di classi, un package o un modulo. Se il tuo diagramma di componenti ha una scatola per classe, sei sceso di un livello di zoom troppo in profondità.

Ogni container ha bisogno di un diagramma di componenti?

No, e cercare di documentare ogni container al livello 3 è uno dei modi più rapidi per abbandonare C4. Crea diagrammi di componenti solo per i container che sono complessi, condivisi tra team o centrali per l'onboarding. Per il resto, il diagramma di container più una struttura di cartelle leggibile è sufficiente.

Quanti componenti dovrebbe mostrare un diagramma di componenti?

All'incirca da 5 a 15. Meno di 5 e il diagramma probabilmente non ti dice nulla che il diagramma di container non dicesse già. Più di 20 e o i confini dei tuoi componenti sono troppo a grana fine, oppure il container stesso dovrebbe essere suddiviso.


Vuoi diagrammi di componenti che restano accurati? Prova Archyl gratis e genera un modello C4 -- componenti inclusi -- dal tuo codice in pochi minuti. Oppure continua a leggere: Cos'è il modello C4? Una guida completa | Guida al diagramma di Container C4 | Guida al diagramma di Codice C4 | Diagramma di Componenti nel glossario.