PlantUML C4-Modell-Syntaxleitfaden

Was ist das C4-Modell-Diagramm?

Die C4-Modell-Diagramm ist ein hierarchisches, vierstufiges architektonisches Framework, das entwickelt wurde, um Softwarearchitekturen mit unterschiedlichen Granularitätsgraden zu dokumentieren. Erstellt von Simon Brown vermeidet C4 vage Boxen und Linien, indem Systemkarten in vier explizite Abstraktionslinsen strukturiert werden: Kontext (Systemebene), Container (Anwendungen und Datenbanken), Komponente (interne Module), und Code (Implementierungen auf Klassenebene).

Um dieses Modell effektiv im Text umzusetzen, verwenden Ingenieure die offizielle C4-PlantUMLStandard-Bibliothekserweiterung. Diese Bibliothek ersetzt rohe UML-Formen durch spezialisierte Makros, die automatisch unterschiedliche Farben, Formen und Metadatenfelder für Benutzer, Systeme und Datenbanken einfügen. Mit VPasCode, können Sie diese verschachtelten Umgebungen sauber im Code definieren. Der Layout-Engine werden Verbindungsvektoren dynamisch geleitet und Textfelder skaliert, ohne Ihre Layout-Geometrie zu stören.

Kern-Syntaxleitfaden: Elemente und Konstrukte

Die Erstellung eines gültigen C4-Modells mit PlantUML beruht auf dem Importieren der richtigen Bibliotheksdateien, der Auswahl struktureller Makros, der Festlegung von Grenzen und der Verwendung spezialisierter Beziehungslinien.

1. Importieren der C4-Standardbibliotheksdateien

Die C4-PlantUMLErweiterung ist in einzelne Dateien aufgeteilt, die direkt den unterschiedlichen Ebenen des Abstraktionsmodells entsprechen. Um Leistungsverzögerungen oder Compiler-Fehler zu vermeiden, sollten Sie nur die spezifische Dateiebene importieren, die Ihr Diagramm anspricht:

@startuml
' Fügen Sie die erforderliche spezifische C4-Ebenendatei ein
!include <C4/C4_Context>
' Verwenden Sie C4_Container oder C4_Component für detailliertere architektonische Karten

2. Deklarieren zentraler Akteure und Systeme (Kontebene)

Auf der hochwertigen Systemkontext-Ebene modellieren Sie interne Komponenten, externe Abhängigkeiten und menschliche Endbenutzer. Die Standardbibliothek bietet spezifische Makros, die eine ID, eine visuelle Beschriftung und einen optionalen beschreibenden Tag akzeptieren:

  • Person(id, "Beschriftung", "Beschreibung") — Stellt ein Benutzerprofil oder einen Systemakteur dar.
  • System(id, "Beschriftung", "Beschreibung") — Stellt ein primäres internes Softwareanwendungssystem oder Dienstekosystem dar.
  • System_Ext(id, "Beschriftung", "Beschreibung") — Stellt ein externes System oder eine Drittanbieter-API-Abhängigkeit dar (wird in einer expliziten grauen Farbpalette dargestellt).
@startuml C4_Elements
!include <C4/C4_Context>
Person(kunde, "Bankkunde", "Ein Kunde mit einem privaten Bankkonto")
System(banking_sys, "Kernbank-System", "Verarbeitet Finanztransaktionen")
System_Ext(mail_sys, "E-Mail-Dienst", "Interner SMTP-Benachrichtigungsgateway")

3. Aufblähende Grenzen (Container- und Komponentenebene)

Wenn Sie tiefer in die Container-Ebene eindringen, modellieren Sie Webanwendungen, Mikrodienste und Datenbanken. Sie können diese internen Elemente innerhalb einer expliziten logischen Grenzbox isolieren, indem Sie dieSystem_Boundary() Makro-Wrapper verwenden:

!include <C4/C4_Container>

System_Boundary(c1, "E-Commerce-System-Ökosystem") {
    Container(web_app, "Einzelseitenanwendung", "React & TypeScript", "Bietet Benutzerfunktionen über Webansicht")
    ContainerDb(database, "Relationale Datenbank", "PostgreSQL", "Speichert Benutzerprofile und Buchungsverläufe")
}

4. Abbildung technischer Beziehungen

Anstatt sich auf einfache gestrichelte Linien zu verlassen, verwendet C4 explizite Kommunikationsmakros im FormatRel(Quell-ID, Ziel-ID, "Beschriftung", "Technologie"). Dadurch bleibt Ihre Architekturkarte sehr lesbar, da jedes Verbindungselement seinen Zweck und das zugrundeliegende Übertragungsprotokoll (z. B. HTTPS, gRPC oder AMQP) angeben muss:

!include <C4/C4_Container>

Person(kunde, "Bankkunde", "Ein Kunde mit einem privaten Bankkonto")
System(banking_sys, "Kernbank-System", "Verarbeitet Finanztransaktionen")
System_Ext(mail_sys, "E-Mail-Dienst", "Interner SMTP-Benachrichtigungsgateway")

System_Boundary(c1, "E-Commerce-System-Ökosystem") {
    Container(web_app, "Einzelseitenanwendung", "React & TypeScript", "Bietet Benutzerfunktionen über Webansicht")
    ContainerDb(database, "Relationale Datenbank", "PostgreSQL", "Speichert Benutzerprofile und Buchungsverläufe")
}
Rel(kunde, web_app, "Nutzt Shop-Funktionen über", "HTTPS")
Rel(web_app, database, "Liest und schreibt transaktionale Daten über", "SQL/TCP")

Best Practices für lesbare C4-Architekturen

  • Abstraktionsstufen niemals mischen:Halten Sie Ihre Diagramme auf einer einzigen Ebene fokussiert. Mischen Sie keine detaillierten internen Softwarekomponenten in eine hochrangige Systemkontextkarte. Wenn ein System zu komplex wird, trennen Sie es in ein separates, speziell dafür erstelltes Container-Ebene-Diagramm.
  • Technologien explizit definieren:Verwenden Sie immer den vierten Parameter in IhrenRel()Makros, um die genaue verwendete Technologie oder das Protokoll anzugeben (z. B."JSON/HTTPS" oder "JDBC"). Dies gibt Ihrem Team einen entscheidenden Implementierungskontext auf einen Blick.
  • Nutzen Sie Richtungs-Layout-Überschreibungen: Wenn Ihre Komponenten unangenehm übereinander stapeln, verwenden Sie Richtungsbeziehungs-Makros (wie Rel_D() für nach unten, Rel_R() für rechts oder Rel_L() für links) um Ihren architektonischen Fluss manuell zu optimieren.

Realitätsnahe PlantUML C4-Beispiele

Beispiel 1: Hochschichtiges Systemkontext-Layout (Ebene 1)

Dieser funktionale Entwurf modelliert ein Standard-Ebene-1-Systemkontext-Diagramm und beschreibt detailliert, wie ein Kunde mit einer Internet-Banking-Anwendung und ihren externen Abhängigkeiten interagiert.

@startuml
!include <C4/C4_Context>

title Systemkontext-Diagramm für Internet-Banking-System

Person(kunde, "Privatkundenkunde", "Ein Kunde der Bank mit privaten Konten.")
System(banking_system, "Internet-Banking-System", "Ermöglicht Kunden, Finanzinformationen einzusehen und Überweisungen durchzuführen.")
System_Ext(mail_system, "E-Mail-Subsystem", "Der interne Unternehmens-SendGrid-Unternehmens-Mailserver-Cluster.")

Rel(kunde, banking_system, "Nutzt Online-Dashboard über")
Rel_R(banking_system, mail_system, "Versendet Warnungen und Bestätigungs-Codes mit", "SMTP")
@enduml

Syntax-Aufschlüsselung: Dieses Diagramm konzentriert sich ausschließlich auf den Hochschichtigen Bereich. Das System_Ext Makro wendet automatisch ein graues Farbprofil auf den E-Mail-Service an und trennt ihn visuell vom Kernsystem und seinen externen Abhängigkeiten. Das Rel_R Makro zwingt den Layout-Engine, den E-Mail-Knoten direkt rechts vom Bank-System-Block zu platzieren.

Beispiel 2: Tiefgang-Mikroservice-Container-Topologie (Ebene 2)

Dieser fortgeschrittene Unternehmensentwurf zerlegt ein System in seine Bestandteile von Container-Anwendungen und isolierten Datenspeichern und zeigt, wie Webverkehr über einen API-Gateway zu Backend-Mikroservices geleitet wird.

@startuml
!include <C4/C4_Container>

title Container-Diagramm für Zahlungsportale-Gateway

Person(händler, "Web-Partner-Händler", "Integriert Plattform-Checkout-Endpunkte in ihre Websites.")

System_Boundary(portal_scope, "Zahlungs-Gateway-Ökosystem") {
    Container(api_gateway, "API-Routing-Proxy", "Nginx", "Empfängt eingehende Aufrufe, handhabt Rate-Limits und verteilt Knoten.")
    Container(auth_service, "Identitäts-Mikroservice", "Go & OAuth2", "Validiert Entwickler-API-Tokens und -Berechtigungen.")
    Container(txn_service, "Transaktions-Protokoll", "Java Spring Boot", "Verarbeitet Zahlungen und verwaltet Protokollkonten.")
    ContainerDb(ledger_db, "Protokoll-Datenspeicher", "CockroachDB", "Implementiert verteilte, ACID-konforme Tabellenschemata.")
}

' Leite Verkehrsflüsse sauber über interne Container-Ziele
Rel(händler, api_gateway, "Übermittelt Zahlungs-Payloads über", "HTTPS/JSON")
Rel_D(api_gateway, auth_service, "Validiert eingehende Tokens über", "gRPC")
Rel_D(api_gateway, txn_service, "Leitet Checkout-Aktionen an", "gRPC")
Rel_R(txn_service, ledger_db, "Speichert Protokoll-Einträge über", "SQL/TLS")
@enduml

Syntax-Aufschlüsselung: Durch die Verwendung der System_Grenze Makro-Wrapper werden interne Komponenten sauber innerhalb einer klaren Umrandungsbox gruppiert. Das spezialisierte ContainerDb Macro rendert den Datenspeicher mit einem expliziten Datenbank-Zylinder-Symbol, wodurch die Unterscheidung zwischen Rechenlaufzeiten und dauerhaften Speicher-Ebenen auf einen Blick klar wird.

Nach oben scrollen