Graphviz DOT-Sprache: der Praxisleitfaden, den dir die offizielle Doku nicht gibt
🇬🇧 English • 🇮🇹 Italiano • 🇪🇸 Español • 🇧🇷 Português
Für Entwickler, Analysten und Softwarearchitekten, die professionelle Diagramme erstellen wollen: klar und schön anzusehen
Was ist die DOT-Sprache? Was ist Graphviz?
DOT ist eine textbasierte Sprache zur Beschreibung von Graphen. Damit beschreibst du Knoten, Kanten und visuelle Attribute mit einer einfachen, gut lesbaren Syntax. Es ist das Standardformat von Graphviz.
Graphviz (Graph Visualization Software) ist eine Open-Source-Werkzeugsammlung zur Visualisierung von Graphen. Ursprünglich bei AT&T Labs entwickelt, liest Graphviz DOT-Dateien und erzeugt daraus Bilder in verschiedenen Formaten (SVG, PNG, PDF). Es ist das weltweit meistgenutzte Werkzeug, um Diagramme aus Code zu erzeugen.
Warum DOT und Graphviz statt grafischer Werkzeuge?
- Versionierbar: DOT-Dateien sind reiner Text, ideal für Git
- Reproduzierbar: Dieselbe Datei erzeugt immer dasselbe Diagramm
- Automatisierbar: Diagramme entstehen in deiner CI/CD-Pipeline
- Schnell: Du schreibst Code, statt Kästchen mit der Maus herumzuschieben
- Professionell: Hochwertige Ausgabe für technische Dokumentation
Vorwort
Warum habe ich dieses Handbuch geschrieben? Weil es Anleitungen zu DOT und Graphviz zwar gibt, sie aber alles abdecken: Biologie, Chemie, soziale Netzwerke, Stammbäume. Jedes Mal musste ich mir heraussuchen, was für Softwareentwickler wirklich zählt. Also habe ich beschlossen, diesen Leitfaden zu schreiben und alles zusammenzutragen, was ich über die Jahre benutzt und immer wieder nachgeschlagen habe. Es war einiges an Arbeit, aber ich hoffe, sie lohnt sich. Jetzt teile ich ihn.
Der Vorteil, Diagramme aus Code zu erzeugen? Die DOT-Datei liegt im Repository, direkt neben dem Quellcode. Wenn du die Architektur änderst, aktualisierst du das Diagramm im selben Commit, es durchläuft dasselbe Code-Review und folgt demselben Workflow. Es ist keine PowerPoint-Datei, die auf irgendeinem Laufwerk vergessen wird und die nie wieder jemand öffnet. Es ist Teil des Projekts.
Und das ist noch nicht alles. DOT-Dateien sind Text, also kannst du sie programmatisch erzeugen. Deine Software kann Diagramme produzieren, die den aktuellen Systemzustand zeigen, die Phasen eines Prozesses, den Weg einer Anfrage durch die Microservices, die Abhängigkeiten zwischen zur Laufzeit geladenen Modulen. Ich habe Teams gesehen, die automatisch Karten ihrer Datenbankmigrationen erzeugen, Graphen der aktiven Feature Flags, sogar Diagramme ihrer Message Queues in Echtzeit. Die Möglichkeiten sind endlos.
Wenn du auch genug hast von Screenshots, die am Tag nach der Aufnahme schon veraltet sind, findest du hier alles, was du für den Einstieg brauchst. Und wenn du DOT einmal beherrschst, wirst du merken, dass Diagramme keine statische Dokumentation mehr sind: Sie werden zu einem lebendigen Teil deines Systems.
Daniele Teti
November 2025
Einführung
In der täglichen Arbeit von Softwareentwicklern, ob Analyst, Backend-Entwickler, Frontend-Entwickler, Datenbankexperte oder Architekt, kommt immer der Moment, in dem ein Diagramm unverzichtbar wird.
Du brauchst eines, wenn du:
- einen komplexen Ablauf erklären musst,
- die CI/CD-Pipeline aufzeichnen willst,
- einem neuen Kollegen die Architektur beschreiben sollst,
- Abhängigkeiten zwischen Modulen analysierst,
- eine Datenbank dokumentierst,
- eine technische Präsentation vorbereitest,
- über ein Refactoring nachdenkst,
- Engpässe finden musst.
Graphviz und seine DOT-Sprache sind dafür ideale Werkzeuge: textbasiert (versionierbar), schnell geschrieben, schön gerendert, flexibel.
Graphviz installieren
Bevor du loslegst, stell sicher, dass Graphviz installiert ist:
- Windows: Lade den Installer von graphviz.org/download herunter oder verwende
winget install graphviz - macOS:
brew install graphviz - Linux:
sudo apt install graphviz(Debian/Ubuntu) odersudo dnf install graphviz(Fedora/RHEL)
Prüfe die Installation mit dot -V: Du solltest die installierte Version sehen.
Dieses Handbuch will der umfassende Leitfaden für alle in der Softwareentwicklung sein, die die DOT-Sprache voll ausschöpfen wollen. Du findest:
- eine gründliche Erklärung der Attribute mit allen relevanten Optionen,
- vollständige, wiederverwendbare und kommentierte Beispiele,
- Best Practices für professionelle Grafiken,
- Hinweise zum Einsatz der Layout-Engines,
- konkrete Szenarien aus der Entwicklungswelt (Design, Refactoring, Analyse, Architektur).
Die DOT-Sprache: solide Grundlagen
DOT beschreibt Graphen mit einer sehr einfachen Syntax:
digraph Name {
nodeA -> nodeB;
}
Oder ungerichtet:
graph Name {
nodeA -- nodeB;
}
Die Grundbegriffe:
- Knoten (nodes): Entitäten (Funktionen, Objekte, Microservices, DB-Tabellen)
- Kanten (edges): Beziehungen, Aufrufe, Abläufe
- Attribute: visuelles Erscheinungsbild oder Metadaten
Quick Start: dein erstes Diagramm in 30 Sekunden
Sofort online testen (ohne etwas zu installieren)
Alle Beispiele in diesem Artikel kannst du direkt online mit Edotor.net ausprobieren:
Geh auf edotor.net
Kopiere den DOT-Code eines beliebigen Beispiels aus diesem Artikel
Füge ihn im linken Bereich ein (und ersetze den vorhandenen Code)
Sieh dir das Rendering sofort im rechten Bereich an
Das ist der schnellste Weg, um zu experimentieren, ohne Graphviz zu installieren. Wenn du für die Produktion bereit bist, installierst du Graphviz lokal.
Erstes Beispiel zum Ausprobieren
Kopiere diesen Code und teste ihn auf edotor.net:
digraph MyFirstGraph {
node [shape=box, style=rounded, fillcolor=lightblue, style="rounded,filled"];
edge [color=blue];
Start -> Process -> End;
Process -> Error [style=dashed, label="on failure"];
Error -> Process [label="retry"];
}
Oder über die lokale Kommandozeile
Lege eine Datei hello.dot mit dem obigen Code an und erzeuge das SVG-Bild:
dot -Tsvg hello.dot -o hello.svg
Öffne hello.svg im Browser und du siehst dein erstes Flussdiagramm! Ab hier basiert alles auf Variationen und Kombinationen dieser Konzepte.
Grundlegende Attribute (mit allen Optionen)
Attribute lassen sich global anwenden auf:
graphnodeedge- einzelne Elemente
Beispiel:
digraph demo {
graph [rankdir=LR];
node [shape=box];
edge [color=grey];
A -> B;
}
Es folgt eine Liste der wichtigsten Attribute mit den Optionen, die in der Softwareentwicklung am nützlichsten sind.
Knotenattribute (node)
shape: Form des Knotens
Nützliche Optionen:
boxellipsecirclediamond(Entscheidungen in Abläufen)record(Klassendiagramme, Datenstrukturen)plaintext(vollständig individueller Inhalt mit HTML-Label)notefolder(in manchen Builds verfügbar)
Beispiel:
node [shape=box];
Typische Verwendung:
- box → Softwaremodule
- ellipse → Zustände
- diamond → Entscheidungen
style: grafischer Stil
Gängige Optionen:
filleddasheddottedboldrounded- Kombinationen:
"filled,rounded"
Beispiel:
node [style="filled,rounded"];
fillcolor: Füllfarbe
Formate:
- Namen (z. B.
"lightgrey") - HEX (z. B.
"#AABBCC") - RGB (
"#rrggbb") - HSL (in manchen Builds)
fontname, fontcolor, fontsize
Z. B.:
node [fontname="Segoe UI", fontsize=12, fontcolor="#333333"];
margin
Innenabstand des Knotens.
node [margin="0.2,0.1"];
width und height: Abmessungen des Knotens
Steuern die Größe der Knoten. Standardmäßig bemisst Graphviz die Knoten automatisch passend zu ihrem Inhalt.
node [width=1.5, height=0.8];
fixedsize: exakte Abmessungen erzwingen:
fixedsize=false(Standard): Der Knoten wächst mit dem Inhalt, width/height gelten als Mindestwertefixedsize=true: Der Knoten hat exakt die mit width/height angegebenen Abmessungen, unabhängig vom Inhaltfixedsize=shape: Gilt nur für die Form, nicht für das Label
Praktische Anwendungsfälle:
- Einheitliches Erscheinungsbild: Verwende
fixedsize=truemitwidth, damit alle Knoten gleich groß sind (unverzichtbar für Zustandsdiagramme und Flussdiagramme) - Flexible Größe: Lass den Standard
fixedsize=false, damit sich die Knoten der Länge des Inhalts anpassen - Nur feste Breite: Kombiniere es mit
height, um das Seitenverhältnis zu steuern
// Alle Zustände gleich groß (professionelle FSM)
node [shape=circle, fixedsize=true, width=0.9];
// Mindestgröße, kann aber wachsen
node [shape=box, width=1.0, fixedsize=false];
label und xlabel: Beschriftungen der Knoten
label: Standardbeschriftung, die im Knoten oder in seiner Nähe angezeigt wird:
A [label="State A"];
Mehrzeilige Labels: Verwende \n für Zeilenumbrüche:
A [label="Main Title\nSubtitle or description"];
xlabel: Externe Beschriftung außerhalb der Knotengrenze. Graphviz sucht automatisch die beste Position, um Überlappungen mit Kanten und anderen Knoten zu vermeiden. Sehr praktisch für Zustandsdiagramme, in denen die Zustände aufgeräumt bleiben sollen:
A [xlabel="State A"];
Praktisches Beispiel: label und xlabel im Vergleich
digraph LabelComparison {
graph [rankdir=LR, fontname="Segoe UI"];
node [shape=circle, fontsize=11, fontname="Segoe UI"];
edge [fontname="Segoe UI"];
subgraph cluster_standard {
label="Using label (internal)";
style=filled;
fillcolor="#F5F5F5";
S1 [label="Idle"];
S2 [label="Running"];
S3 [label="Done"];
S1 -> S2 [label="start"];
S2 -> S3 [label="finish"];
S3 -> S1 [label="reset"];
}
subgraph cluster_external {
label="Using xlabel (external)";
style=filled;
fillcolor="#F5F5F5";
X1 [xlabel="Idle"];
X2 [xlabel="Running"];
X3 [xlabel="Done"];
X1 -> X2 [label="start"];
X2 -> X3 [label="finish"];
X3 -> X1 [label="reset"];
}
}
Wann du xlabel verwendest:
- Zustandsdiagramme: Die Zustandskreise bleiben optisch sauber
- Komplexe Graphen: Weniger visuelles Durcheinander in den Knoten
- Automatische Positionierung: Graphviz findet die optimale Position der Beschriftung
- Kleine Knoten: Wenn interne Labels die Knoten zu groß machen würden
Notizen und Anmerkungen an Knoten
Es gibt mehrere Techniken, um den Knoten deiner Diagramme erklärende Notizen, Beschreibungen oder Anmerkungen hinzuzufügen. Besonders nützlich sind sie für Mindmaps, Dokumentation und komplexe Architekturen.
Technik 1: Mehrzeilige Labels mit \n
Der einfachste Ansatz: Zeilenumbrüche direkt im Label.
Concept [label="Main Concept\n(This is a note explaining the concept)"];
Technik 2: Tooltip mit dem Attribut tooltip
Ein Tooltip, der beim Überfahren mit der Maus erscheint (funktioniert im SVG, wenn es im Browser angezeigt wird):
Node [label="Cloud Storage", tooltip="Amazon S3, Azure Blob, Google Cloud Storage"];
Technik 3: Eigener Notizknoten, mit gestrichelter Kante verbunden
Ein eigener Notizknoten, der sich optisch von den Hauptknoten abhebt:
MainNode [label="User Service"];
Note1 [shape=note, label="Handles authentication\nand user profiles", fillcolor="#FFFACD"];
MainNode -> Note1 [style=dashed, arrowhead=none, color="#CCCCCC"];
Technik 4: HTML-ähnliche Labels mit der Form record
Strukturierte Records trennen den Titel von der Beschreibung:
node [shape=record];
Concept [label="{Concept Name|Description or note\labout this concept}"];
Vollständiges Beispiel: Mindmap mit Notizen
graph MindMapWithNotes {
graph [layout=fdp, K=0.6, fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#E3F2FD", fontsize=11, fontname="Segoe UI"];
edge [color="#888888", fontname="Segoe UI"];
// Hauptkonzept (zentral)
Central [label="Project\nArchitecture", fillcolor="#BBDEFB", fontsize=14, width=2.0, height=1.0, pin=true, pos="0,0!"];
// Unterkonzepte (rund um das Zentrum)
Frontend [label="Frontend\nReact + TypeScript", width=1.8];
Backend [label="Backend\nNode.js + Express", width=1.8];
Database [label="Database\nPostgreSQL", width=1.5];
DevOps [label="DevOps\nDocker + CI/CD", width=1.5];
// Notizknoten (an die Konzepte gehängt)
FrontendNote [shape=note, label="Uses Redux\nfor state mgmt", fillcolor="#FFFACD", fontsize=10];
BackendNote [shape=note, label="RESTful API\n+ WebSocket", fillcolor="#FFFACD", fontsize=10];
DatabaseNote [shape=note, label="PostgreSQL\n+ migrations", fillcolor="#FFFACD", fontsize=10];
DevOpsNote [shape=note, label="Automated\ndeployments", fillcolor="#FFFACD", fontsize=10];
// Hauptverbindungen (Äste der Mindmap)
Central -- Frontend;
Central -- Backend;
Central -- Database;
Central -- DevOps;
// Notizen mit gestrichelten Linien angehängt (ohne Pfeile)
Frontend -- FrontendNote [style=dashed, color="#CCCCCC"];
Backend -- BackendNote [style=dashed, color="#CCCCCC"];
Database -- DatabaseNote [style=dashed, color="#CCCCCC"];
DevOps -- DevOpsNote [style=dashed, color="#CCCCCC"];
}
Wann welche Technik passt:
| Technik | Am besten für | Vorteile | Nachteile |
|---|---|---|---|
Mehrzeilig \n | Kurze Notizen (1-2 Zeilen) | Einfach, immer sichtbar | Kann Knoten zu groß machen |
tooltip | Lange Erklärungen | Überlädt das Diagramm nicht | Funktioniert nur im interaktiven SVG |
| Eigener Notizknoten | Wichtige Anmerkungen | Sehr sichtbar, gestaltbar | Mehr visuelle Komplexität |
| HTML-Record | Strukturierte Daten | Saubere Trennung | Komplexere Syntax |
Kantenattribute (edge)
arrowsize
Skalierung der Pfeilspitze. Standard ~1.0
edge [arrowsize=0.8];
arrowhead / arrowtail
Nützliche Optionen:
normalempty(hohles Dreieck, sehr gut lesbar)diamondonormalcrow(ER-Diagramme)teenone
style und color
edge [style=dashed, color="#888888"];
label
Beschriftung der Kante.
A -> B [label="calls"];
Graph-Attribute (graph)
rankdir
Layoutrichtung (nur dot):
TB(oben → unten)BT(unten → oben)LR(links → rechts)RL(rechts → links)
Z. B.:
graph [rankdir=LR];
splines
Steuert die Form der Kanten:
true(Standard)false(gerade Linien)polylineortho(orthogonal, ideal für “Architekten”-Diagramme)
ranksep, nodesep
Horizontale/vertikale Abstände.
graph [ranksep=0.8, nodesep=0.6];
Wie definiert man in DOT Stile für Knotengruppen?
Eine der häufigsten Fragen bei Graphviz lautet: Wie wende ich denselben Stil auf eine Gruppe von Knoten an, ohne ihn für jeden einzelnen zu wiederholen?
Die Antwort ist einfach: Liste die Knoten in derselben Zeile auf, gefolgt von der Attributdefinition. DOT wendet diese Attribute auf alle aufgeführten Knoten an.
Syntax für das Stylen von Knotengruppen
Methode 1: Knoten-Defaults neu definieren (empfohlen)
// Node-Defaults vor jeder Gruppe neu definieren
node [shape=box, style=filled, fillcolor="#E8F4F8"];
A; B; C;
node [shape=ellipse, style=filled, fillcolor="#FFF4E6", fontname="Segoe UI"];
D; E; F;
node [shape=diamond, style=filled, fillcolor="#FFE8E8"];
G; H; I;
Methode 2: Knoten mit Attributen auflisten
// Alternative: Knoten durch Semikolons getrennt auflisten, der letzte mit Attributen
A; B; C [shape=box, style=filled, fillcolor="#E8F4F8"];
D; E; F [shape=ellipse, style=filled, fillcolor="#FFF4E6"];
G; H; I [shape=diamond, style=filled, fillcolor="#FFE8E8"];
Hinweis: Methode 1 ist über verschiedene Graphviz-Versionen hinweg zuverlässiger und macht es leichter, später Knoten zu einer Kategorie hinzuzufügen.
Diese Technik ist unverzichtbar, wenn du komplexe Diagramme mit Dutzenden Knoten aus verschiedenen Kategorien hast.
Praxisbeispiel: Knoten nach Rolle kategorisieren
Stell dir vor, du musst eine Architektur mit drei Arten von Komponenten zeichnen: Services (blaue Kästen), Datenbanken (grüne Zylinder), Queues/Nachrichten (orange Ellipsen).
digraph Architecture {
graph [rankdir=LR, nodesep=0.8, fontname="Segoe UI"];
node [fontname="Segoe UI"];
edge [fontname="Segoe UI"];
// Services - blaue Kästen
node [shape=box, style="filled,rounded", fillcolor="#E3F2FD"];
AuthService; UserService; OrderService; NotificationService;
// Datenbanken - grüne Zylinder
node [shape=cylinder, style=filled, fillcolor="#E8F5E9"];
UserDB; OrderDB; SessionCache;
// Message Queues - orange Ellipsen
node [shape=ellipse, style=filled, fillcolor="#FFF3E0"];
EmailQueue; SMSQueue; PushQueue;
// Beziehungen
AuthService -> SessionCache;
UserService -> UserDB;
OrderService -> OrderDB;
OrderService -> EmailQueue;
NotificationService -> EmailQueue;
NotificationService -> SMSQueue;
NotificationService -> PushQueue;
}
Was dieses Beispiel macht: Es definiert drei Knotenkategorien mit unterschiedlichen Stilen in nur drei Zeilen. Services sind abgerundete blaue Kästen, Datenbanken grüne Zylinder, Queues orange Ellipsen. Jede Kategorie ist auf einen Blick erkennbar.
Warum diese Technik?
- DRY-Code (Don’t Repeat Yourself): Du wiederholst
shape=box, style=fillednicht für jeden Knoten - Wartbarkeit: Um die Farbe aller Services zu ändern, genügt eine einzige Änderung
- Lesbarkeit: Der DOT-Code dokumentiert sich selbst (du siehst sofort, welche Knoten Services und welche DBs sind)
- Skalierbarkeit: Ein neuer Service bedeutet nur, seinen Namen zur Liste hinzuzufügen
Kombination mit Standardattributen
Du kannst diese Technik für maximale Flexibilität mit Standardattributen kombinieren:
digraph Mixed {
// Standard für alle Knoten
node [fontname="Segoe UI", fontsize=11];
// Dann nach Gruppe spezialisieren
Input; Validation [shape=parallelogram, fillcolor="#B3E5FC", style=filled];
Process; Transform [shape=box, fillcolor="#C8E6C9", style=filled];
Output; Export [shape=parallelogram, fillcolor="#FFCCBC", style=filled];
Error [shape=octagon, fillcolor="#FFCDD2", style=filled];
Input -> Validation -> Process -> Transform -> Output -> Export;
Validation -> Error;
Process -> Error;
}
Was dieses Beispiel macht: Es legt einen gemeinsamen Standard fest (Schrift Arial 11pt) und dann drei Gruppen: Input/Output als Parallelogramme (Flussdiagramm-Konvention), Verarbeitungsschritte als Kästen, Fehler als rote Achtecke.
Layout-Engines: die richtige wählen
Graphviz hat nicht nur eine Rendering-Engine, sondern mehrere, jede für bestimmte Arten von Graphen optimiert. Die richtige Engine zu wählen heißt, lesbarere und professionellere Diagramme zu bekommen.
Die Engine gibst du auf der Kommandozeile mit dem Flag -K an:
dot -Kdot -Tsvg file.dot -o output.svg
dot -Kneato -Tsvg file.dot -o output.svg
Oder direkt in der DOT-Datei:
graph G {
layout=neato;
// ...
}
Es folgen die wichtigsten Engines und wann du sie einsetzt.
Verfügbare Layout-Engines
dot: hierarchisches Layout (Standard)
Was sie macht: Ordnet die Knoten hierarchisch an und folgt dabei der Richtung der Kanten. Sie ist die meistgenutzte.
Perfekt für:
- Flussdiagramme und Ablaufdiagramme
- CI/CD-Pipelines
- Call Graphs (Graph der Aufrufe zwischen Funktionen)
- Schichtenarchitekturen (Presentation → Business → Data)
- Sequenzielle Prozesse
- Abhängigkeitsdiagramme mit klarer Richtung
Beispielbefehl:
dot -Tsvg flowchart.dot -o flowchart.svg
Visuelles Beispiel:
digraph DotExample {
graph [rankdir=TB, fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#E3F2FD", fontname="Segoe UI"];
A -> B -> C;
A -> D -> C;
B -> E;
D -> E;
}
Was du siehst: Knoten in klaren hierarchischen Ebenen von oben nach unten. Perfekt, um Abläufe und Abhängigkeiten zu zeigen.
Wann du sie meiden solltest: Wenn der Graph keine klare hierarchische Struktur hat oder viele Zyklen enthält.
neato: Force-directed-Layout
Was sie macht: Positioniert die Knoten, indem sie physikalische Kräfte simuliert (Abstoßung/Anziehung), und erzeugt so organische, symmetrische Layouts.
Nützlich für:
- Ungerichtete Graphen (ohne Pfeile)
- Begriffsnetze und Mindmaps
- Nicht hierarchische Beziehungen zwischen Entitäten
- Kleine bis mittlere Graphen, in denen natürliche Cluster sichtbar werden sollen
Beispielbefehl:
dot -Kneato -Tsvg concepts.dot -o concepts.svg
Visuelles Beispiel (derselbe Graph wie oben, andere Engine):
graph NeatoExample {
graph [layout=neato, fontname="Segoe UI"];
node [shape=ellipse, style=filled, fillcolor="#FFF4E6", fontname="Segoe UI"];
A -- B -- C;
A -- D -- C;
B -- E;
D -- E;
}
Was du siehst: Knoten organisch im 2D-Raum verteilt, mit natürlicher Gruppierung. Perfekt für Mindmaps und Begriffsnetze mit nicht hierarchischen Beziehungen.
Wann du sie meiden solltest: Bei sehr großen Graphen (>100 Knoten) oder stark gerichteten.
fdp: Force-directed Placement
Was sie macht: Ähnlich wie neato, aber mit einem anderen Algorithmus (Fruchterman-Reingold). Auf mittleren Graphen meist schneller.
Nützlich für:
- Mittelgroße ungerichtete Graphen
- Visualisierung sozialer Netzwerke (Freundschaften, Verbindungen)
- Abhängigkeitsanalyse ohne ausgeprägte Richtung
Beispielbefehl:
dot -Kfdp -Tsvg network.dot -o network.svg
sfdp: skalierbares Force-directed Placement
Was sie macht: Für sehr große Graphen (Tausende Knoten) optimierte Version von fdp.
Hervorragend für:
- Abhängigkeitsanalyse komplexer Codebasen
- Klassengraph eines Enterprise-Projekts
- Komplexe Netze (Infrastruktur, Microservices)
- Wenn
neatooderfdpzu langsam sind
Beispielbefehl:
dot -Ksfdp -Tsvg dependencies.dot -o dependencies.svg
Tipp: Verwende sfdp ab etwa 100-200 Knoten.
circo: kreisförmiges Layout
Was sie macht: Ordnet die Knoten in konzentrischen Kreisen um einen zentralen Knoten an.
Ideal für:
- Satellitenmodule rund um einen zentralen Kern darstellen
- Hub-and-Spoke-Architekturen
- Komponenten, die von einem zentralen Service abhängen
Beispielbefehl:
dot -Kcirco -Tsvg modules.dot -o modules.svg
Visuelles Beispiel:
graph CircoExample {
graph [layout=circo, fontname="Segoe UI"];
node [shape=circle, style=filled, fillcolor="#E8F5E9", fontname="Segoe UI"];
Core -- Module1;
Core -- Module2;
Core -- Module3;
Core -- Module4;
Core -- Module5;
Module1 -- Module2;
Module3 -- Module4;
}
Was du siehst: Der zentrale Knoten (Core) in der Mitte, die Satelliten im Kreis darum. Perfekt für Hub-and-Spoke-Architekturen.
twopi: radiales Layout
Was sie macht: Erzeugt ein radiales Baumlayout mit dem Wurzelknoten in der Mitte und Ebenen, die sich nach außen ausbreiten.
Perfekt für:
- Hierarchische Bäume (Organigramm, Dateisystem)
- Taxonomien
- Strukturierte Mindmaps
- Ausbreitung von einem zentralen Punkt aus
Beispielbefehl:
dot -Ktwopi -Tsvg tree.dot -o tree.svg
Visuelles Beispiel:
digraph TwopiExample {
graph [layout=twopi, ranksep=2.0, fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#FFEBEE", fontsize=11, width=1.0, height=0.5, fontname="Segoe UI"];
edge [color="#666666", fontname="Segoe UI"];
CEO [label="CEO", fillcolor="#FFCDD2"];
CEO -> Engineering [label=""];
CEO -> Sales [label=""];
CEO -> Marketing [label=""];
Engineering -> Dev1 [label=""];
Engineering -> Dev2 [label=""];
Sales -> Rep1 [label=""];
Sales -> Rep2 [label=""];
Marketing -> Designer [label=""];
Marketing -> Writer [label=""];
}
Was du siehst: Der CEO in der Mitte, die Abteilungen (Engineering, Sales, Marketing) im ersten Ring und die Teammitglieder im äußeren Ring. Eine klare radiale Hierarchie, perfekt für Organigramme.
Wie du in der Praxis wählst
| Art des Graphen | Empfohlene Engine |
|---|---|
| Flussdiagramm, Pipeline, Prozesse | dot |
| Schichtenarchitekturen | dot |
| Call Graph, Abhängigkeitsbaum | dot |
| Begriffsnetz, Brainstorming | neato |
| Soziales Netzwerk, mittlere ungerichtete Graphen | fdp |
| Große Graphen (>200 Knoten) | sfdp |
| Zentraler Hub mit Satelliten | circo |
| Hierarchische Bäume, Organigramm | twopi |
Faustregel: Hast du Pfeile und eine klare Richtung → nimm dot. Sonst probiere neato oder fdp.
Diagrammtypen und wann du sie im echten Entwickleralltag brauchst
Das ist der umfangreichste Abschnitt. Zu jedem Diagrammtyp findest du:
- Wann du es im echten Leben einsetzt
- Empfohlene Attribute
- Vollständiges Beispiel
Flussdiagramm: Verhalten verstehen
Im Arbeitsalltag musst du oft einen komplexen Entscheidungsablauf erklären: eine Validierung mit mehreren Verzweigungen, einen Onboarding-Prozess für Benutzer oder einfach das Verhalten einer Funktion mit vielen verschachtelten if/else. Das Flussdiagramm ist dafür das ideale Werkzeug.
Wann du ein Flussdiagramm brauchst:
Du bist in der Anforderungsanalyse und musst alle möglichen Fälle verstehen. Du debuggst eine Logik, die verrückt zu spielen scheint, und willst sehen, wo sich der Ablauf verzweigt. Du musst die Dokumentation eines komplexen Geschäftsprozesses schreiben. Du arbeitest einen neuen Kollegen ein und willst ihm zeigen, wie das Authentifizierungssystem funktioniert.
Das Flussdiagramm zeigt visuell Entscheidungen (Rauten), Verarbeitungsschritte (abgerundete Rechtecke) und den logischen Ablauf (Pfeile). Es ist unmittelbar, klar, universell.
Empfohlene Attribute für professionelle Flussdiagramme:
Verwende rankdir=TB (von oben nach unten), um der üblichen Flussdiagramm-Konvention zu folgen. Verwende shape=diamond für Entscheidungsknoten (if/else-Bedingungen). Verwende style=rounded für die Verarbeitungsschritte, damit sie sich von den Rauten abheben. Verwende sanfte Farben (fillcolor), um Start (hellgrün), Fehler (hellrot) und Ende (grau) hervorzuheben.
Vollständiges Beispiel:
digraph Flow {
graph [rankdir=TB, nodesep=0.6];
node [fontname="Segoe UI"];
Start [shape=oval, style=filled, fillcolor="#C1F2C7"];
Check [shape=diamond, label="Valid input?"];
Process [shape=box, style="filled,rounded", fillcolor="#F0F4FF"];
Error [shape=box, fillcolor="#FFEAEA", style=filled];
End [shape=oval, fillcolor="#DDDDDD", style=filled];
Start -> Check;
Check -> Process [label="yes"];
Check -> Error [label="no"];
Process -> End;
}
Was dieses Beispiel macht: Es beginnt bei einem Anfangszustand (Start), durchläuft die Validierung (Check) und verzweigt sich in zwei Pfade: Erfolg (Process) oder Fehler (Error). Die Farben machen sofort klar, was positiv und was negativ ist.
Abhängigkeitsgraphen: Software als System verstehen
Wenn du an einem bestehenden Projekt arbeitest, lautet eine der ersten Fragen: “Was hängt wovon ab?” Musst du ein Modul refaktorieren, willst du wissen, wer es verwendet. Musst du eine Bibliothek aktualisieren, willst du die Folgewirkungen verstehen. Entwirfst du ein neues Feature, willst du sehen, wo es in die bestehende Architektur passt.
Der Abhängigkeitsgraph ist die Landkarte deines Systems. Er zeigt Module, Services, Klassen oder Microservices als Knoten und Abhängigkeiten als Pfeile. Unverzichtbar ist er für:
Sicheres Refactoring: Bevor du ein Modul anfasst, siehst du, wer es aufruft. Impact-Analyse: Änderst du eine API, siehst du sofort alle Konsumenten. Automatische Dokumentation: Erzeuge den Graphen aus dem Code (mit Werkzeugen wie Doxygen, Madge oder eigenen Skripten) und halte ihn aktuell. Dependency-Injection-Mapping: Visualisiere, wie Spring, Angular oder .NET die Abhängigkeiten injizieren.
Nützliche Attribute:
Verwende rankdir=LR (von links nach rechts) für einen horizontalen Ablauf, typisch für Abhängigkeitsketten. Verwende shape=box für Module/Services. Verwende color und penwidth, um kritische oder problematische Abhängigkeiten hervorzuheben (z. B. zirkuläre Abhängigkeiten in Rot). Verwende style=dashed für optionale oder schwache Abhängigkeiten.
Beispiel:
digraph Deps {
graph [rankdir=LR];
node [shape=box, style=filled, fillcolor="#F7FAFF", fontname="Segoe UI"];
edge [color="#555555"];
UI -> API;
API -> Auth;
API -> UserService;
UserService -> Database [color="#FF5555", penwidth=2, label="critical"];
}
Was dieses Beispiel macht: Es zeigt eine klassische Webarchitektur: Die UI ruft die API auf, die API hängt von Auth und UserService ab, UserService spricht mit der Datenbank. Die kritische Abhängigkeit (UserService → Database) ist rot und mit dicker Linie hervorgehoben: Fällt die DB aus, bricht alles zusammen.
Softwarearchitektur: Cluster und Schichten
Wenn du eine Architektur entwirfst oder die bestehende dokumentierst, musst du logische Gruppierungen und die Trennung der Schichten zeigen. Ein typisches Websystem hat Presentation, Business und Data. Ein Microservices-Projekt hat logische Grenzen (Edge, Services, Datastores). Ein Legacy-System hat vielleicht nach Domäne getrennte Module.
Das Architekturdiagramm mit Clustern ermöglicht dir:
Getrennte Schichten darstellen: Presentation Layer, Business Layer, Data Layer. Jede Schicht ist ein farbiger Kasten mit ihren Komponenten. Grenzen der Microservices zeigen: Edge Gateway, Services, Datastores. Jede Grenze ist ein Cluster. Legacy-Module dokumentieren: Isoliere die Module nach Verantwortung (Auth, Orders, Reporting), damit klar ist, wer was macht. Stakeholdern die Architektur präsentieren: Ein Schichtendiagramm ist universell und auch für Nicht-Techniker verständlich.
Nützliche Attribute:
Verwende subgraph cluster_*, um visuelle Gruppierungen zu erzeugen. Verwende compound=true, um Kanten zu erlauben, die Cluster überqueren. Verwende splines=ortho für orthogonale Linien, typisch für “Architekten”-Diagramme. Verwende shape=cylinder für Datenbanken, damit sie sofort erkennbar sind.
Beispiel einer Schichtenarchitektur:
digraph Architecture {
graph [
rankdir=TB,
ranksep=0.8,
nodesep=0.6,
overlap=false,
splines=true,
sep="+0.2"
];
node [shape=box, style="rounded,filled", fillcolor="#F0F4FF", fontname="Segoe UI"];
subgraph cluster_presentation {
label="Presentation Layer";
style=filled;
color=lightgrey;
fillcolor="#E8F4F8";
UI;
}
subgraph cluster_business {
label="Business Layer";
style=filled;
color=lightgrey;
fillcolor="#FFF4E6";
ServiceA; ServiceB;
}
subgraph cluster_data {
label="Data Layer";
style=filled;
color=lightgrey;
fillcolor="#F0F0F0";
DB [shape=cylinder, fillcolor="#D0E8FF"];
}
UI -> ServiceA;
UI -> ServiceB;
ServiceA -> DB;
ServiceB -> DB;
}
Was dieses Beispiel macht: Es definiert drei Schichten mit subgraph cluster_*. Presentation enthält die UI, Business zwei Services, Data die DB (mit shape=cylinder). Die Pfeile zeigen den Ablauf: UI → Services → DB. Die Architektur ist auf einen Blick verständlich.
Microservices-Karte: ein verteiltes Ökosystem verstehen
Wenn du mit Microservices arbeitest, hast du Dutzende Services, die miteinander kommunizieren: API Gateway, Domänen-Services (Orders, Users, Notifications), Datenbanken, Queues, Caches. Wenn in der Produktion ein Incident auftritt, lautet die erste Frage: “Wer spricht mit wem? Wo ist der Engpass?”
Die Microservices-Karte ist dein Navi im verteilten Chaos. Du brauchst sie für:
Architekturentwurf: Bevor du Code schreibst, zeichne die Karte. Identifiziere die logischen Grenzen (Edge, Core Services, Datastores). API-Dokumentation: Zeige, wer welchen Service über welches Protokoll aufruft (REST, gRPC, Events). Performance-Analyse: Während eines Incidents schaust du auf die Karte und verstehst sofort, ob das Problem im API Gateway, in einem bestimmten Service oder in der gemeinsamen DB liegt. Post-Mortem: Nach einem Ausfall hilft die Karte, die Fehlerkette zu rekonstruieren.
Nützliche Attribute:
Verwende cluster, um logische Grenzen zu trennen (Edge, Services, Data). Verwende shape=cylinder für Datenbanken, shape=box für Services. Verwende Labels an den Kanten, um das Protokoll anzugeben (HTTP, gRPC, Kafka). Verwende shape=plaintext mit HTML-Tabelle für komplexe Services mit mehreren Ports.
Beispiel:
digraph Micro {
// Globale Einstellungen (gelten für alles)
graph [rankdir=LR, splines=true, nodesep=1.2, ranksep=1.8, overlap=false, sep="+0.4", fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#E3F2FD", fontname="Segoe UI", fontsize=11];
edge [color="#555555", arrowsize=0.8, fontsize=10, fontcolor="#333333", fontname="Segoe UI"];
subgraph cluster_gateway {
label="Edge Layer";
fillcolor="#FFF3E0";
color="#FF9800";
Gateway [label="API Gateway", fillcolor="#FFE0B2"];
}
subgraph cluster_services {
label="Microservices Layer";
fillcolor="#E8F5E9";
color="#4CAF50";
OrderService [label="Order Service", fillcolor="#C8E6C9"];
UserService [label="User Service", fillcolor="#C8E6C9"];
NotificationService [label="Notification Service", fillcolor="#C8E6C9"];
}
subgraph cluster_data {
label="Data Layer";
fillcolor="#F5F5F5";
color="#9E9E9E";
DB [shape=cylinder, label="Postgres\nDB", fillcolor="#BBDEFB"];
Cache [shape=cylinder, label="Redis\nCache", fillcolor="#FFCCBC"];
}
// Edge zu den Services
Gateway -> UserService [label="HTTP"];
Gateway -> OrderService [label="HTTP"];
// Service zu den Daten
OrderService -> DB [label="SQL"];
UserService -> Cache [label="GET/SET"];
// Service zu Service
NotificationService -> UserService [label="gRPC"];
OrderService -> NotificationService [label="Event", style=dashed];
}
Was dieses Beispiel macht: Es gliedert ein Microservices-Ökosystem in drei farbige Schichten:
- Edge Layer (orange): API Gateway als Einstiegspunkt
- Microservices Layer (grün): drei Services mit klaren Verantwortlichkeiten
- Data Layer (grau): Postgres-Datenbank und Redis-Cache (Zylinder zur optischen Unterscheidung)
Gezeigte Kommunikationsmuster:
- Gateway → Services: HTTP-Aufrufe (durchgezogene Pfeile)
- Services → Data: SQL-Abfragen und Cache-Operationen
- Service-to-Service: synchroner gRPC-Aufruf und asynchrones Event (gestrichelter Pfeil)
Die farbcodierten Cluster zeigen sofort die Architekturgrenzen, und die beschrifteten Pfeile machen die Protokolle explizit. Perfekt für Onboarding, Architektur-Reviews oder die Analyse von Incidents.
Zustandsdiagramme: Verhalten modellieren
Viele Systeme haben ein zustandsbasiertes Verhalten: Eine HTTP-Anfrage kann Idle, Loading, Success oder Error sein. Eine E-Commerce-Bestellung geht von Draft → Pending → Confirmed → Shipped. Ein Embedded-System hat die Zustände Einschalten, Standby, Betrieb, Fehler. Eine Benutzeroberfläche hat die Zustände Laden, Bereit, Fehler.
Das Zustandsdiagramm modelliert dieses Verhalten als Graph: Jeder Knoten ist ein Zustand, jede Kante ein Übergang, beschriftet mit dem Ereignis, das ihn auslöst. Unverzichtbar ist es für:
Zustandsautomaten entwerfen: Bevor du das State Pattern im Code umsetzt, zeichne das Diagramm. Protokolle dokumentieren: Netzwerkprotokolle (TCP, WebSocket, eigene) haben präzise Zustandsautomaten. Das Diagramm macht sie explizit. UI/UX-Abläufe modellieren: Wenn du eine App entwirfst, zeichne die Zustände der Oberfläche: Laden, Bereit, Fehler, Leer. Embedded-Systeme debuggen: Bleibt ein Gerät in einem Zustand hängen, hilft dir das Diagramm zu verstehen, welche Übergänge fehlen.
Verbindung zur Informatik-Theorie und zu Design Patterns:
Zustandsdiagramme in DOT bilden grundlegende Konzepte der Informatik und des Softwaredesigns direkt ab:
FSM (Finite State Machine, endlicher Automat): Ein Berechnungsmodell mit einer endlichen Anzahl von Zuständen. Das Diagramm zeigt alle möglichen Zustände und die Übergänge zwischen ihnen. Eingesetzt in Compilern, Parsern und Protokollimplementierungen.
DFA (Deterministic Finite Automaton, deterministischer endlicher Automat): Eine besondere Art von FSM, bei der jeder Zustand pro Eingabesymbol genau einen Übergang hat. Zustandsdiagramme sind die visuelle Darstellung der DFAs, die in der Theorie formaler Sprachen und in Engines für reguläre Ausdrücke verwendet werden.
State Pattern (GoF-Design-Pattern): Ein objektorientiertes Entwurfsmuster, mit dem ein Objekt sein Verhalten ändern kann, wenn sich sein interner Zustand ändert. Das Zustandsdiagramm wird zum Bauplan für die Umsetzung des Patterns: Jeder Kreis ist eine Klasse, die das Interface State implementiert, jeder Pfeil eine Methode für den Zustandsübergang.
Wenn du ein Zustandsdiagramm zeichnest, erstellst du nicht nur Dokumentation: Du erstellst eine formale Spezifikation, die sich direkt in Code übersetzen (State Pattern), zur Validierung verwenden (DFA) oder auf Korrektheit analysieren lässt (FSM-Theorie).
Nützliche Attribute:
Verwende shape=circle für Zustände (übliche FSM-Konvention). Verwende rankdir=LR für ein horizontales Layout, typisch für Zustandsdiagramme. Verwende label an den Kanten, um das Ereignis zu zeigen, das den Übergang auslöst. Verwende shape=doublecircle für End- bzw. Terminalzustände. Verwende fixedsize=true mit width, damit alle Kreise für ein einheitliches Bild gleich groß sind.
Anfangs- und Endzustände darstellen (FSM/DFA-Standard):
Nach den Konventionen für endliche Automaten und DFAs gilt:
- Anfangszustand: Verwende
shape=pointmit kleinerwidth(z. B. 0.2), um einen schwarzen Punkt als Einstiegspunkt zu erzeugen - End-/Akzeptanzzustand: Verwende
shape=doublecirclefür einen doppelten Kreisrand, der Terminal- bzw. Akzeptanzzustände kennzeichnet - Normale Zustände: Verwende
shape=circlemitfixedsize=truefür alle Zwischenzustände (sorgt für ein einheitliches Bild)
Vollständiges Beispiel mit korrekter FSM-Notation:
digraph States {
graph [rankdir=LR, fontname="Segoe UI"];
node [shape=circle, fontsize=12, fixedsize=true, width=0.9, fontname="Segoe UI"];
edge [fontname="Segoe UI"];
// Anfangszustand (schwarzer Punkt)
START [shape=point, width=0.2, fixedsize=true];
// Endzustand (doppelter Kreis)
END [shape=doublecircle, fixedsize=true, width=0.9];
// Normale Zustände
Idle; Loading; Ready; Error;
// Übergänge
START -> Idle;
Idle -> Loading [label="start"];
Loading -> Ready [label="success"];
Loading -> Error [label="fail"];
Error -> Idle [label="reset"];
Ready -> END [label="finish"];
}
Was dieses Beispiel macht: Es modelliert den Lebenszyklus einer asynchronen Anfrage nach den FSM/DFA-Konventionen:
- START (
shape=point): schwarzer Punkt als Einstiegspunkt des Zustandsautomaten - END (
shape=doublecircle): doppelter Kreis als Akzeptanz- bzw. Terminalzustand - Normale Zustände (Idle, Loading, Ready, Error): einheitliche Kreise (
fixedsize=true, width=0.9) für die Zwischenzustände - Beschriftete Übergänge: Pfeile mit den Ereignissen, die die Zustandswechsel auslösen
Der Automat beginnt bei START, geht in Idle über und wechselt dann zu Loading. Von Loading aus kann er erfolgreich sein (→ Ready) oder scheitern (→ Error). Fehler lassen sich auf Idle zurücksetzen. Der Erfolg führt zum Endzustand END.
Vom Diagramm zum Code (Umsetzung des State Pattern):
Dieses Diagramm lässt sich direkt in das State Pattern übersetzen:
// Jeder Kreis wird zu einer State-Klasse
interface State {
void start();
void success();
void fail();
void reset();
void finish();
}
class IdleState implements State { ... }
class LoadingState implements State { ... }
class ReadyState implements State { ... }
class ErrorState implements State { ... }
// Übergänge werden zu Methodenimplementierungen
class LoadingState implements State {
void success() {
context.setState(new ReadyState());
}
void fail() {
context.setState(new ErrorState());
}
}
Das Diagramm dient zugleich als Dokumentation und als Spezifikation der Implementierung.
Klassendiagramme mit record
Wenn du ein objektorientiertes System entwirfst oder die Domäne einer Anwendung dokumentieren willst, ist das Klassendiagramm der Standard. Es zeigt Klassen mit Attributen und Methoden sowie die Beziehungen zwischen ihnen (Vererbung, Komposition, Abhängigkeit).
DOT ist kein UML, aber mit shape=record bekommst du etwas sehr Ähnliches, das sich bestens lesen lässt. Nützlich ist das für:
Erster Entwurf: Bevor du Code schreibst, zeichne die wichtigsten Domänenklassen. Identifiziere Attribute, Methoden, Beziehungen. Refactoring: Wenn du ein Modul umbauen musst, zeichne den aktuellen und den gewünschten Zustand. Vergleiche die beiden Diagramme. Domain-Driven Design (DDD): Modelliere Entities, Value Objects, Aggregates. Das Diagramm hilft, die Grenzen der Domäne sichtbar zu machen. Dokumentation: Erzeuge das Diagramm automatisch aus dem Code (mit Werkzeugen wie Doxygen) und halte es aktuell.
Nützliche Attribute:
Verwende shape=record, um Kästen mit getrennten Abschnitten zu erzeugen (Klassenname | Attribute | Methoden). Verwende fontname="Segoe UI" oder eine Monospace-Schrift, damit es wie Code aussieht. Verwende arrowhead=onormal für Vererbung (hohler Pfeil, UML-Standard). Verwende \l (Backslash-l), um den Text im Record linksbündig auszurichten.
Beispiel:
digraph Classes {
node [shape=record, fontname="Segoe UI"];
Person [label="{Person|name: string\l age: int\l|greet()}"];
Employee [label="{Employee|id: int\l role: string\l|work()}"];
Person -> Employee [arrowhead="onormal"];
}
Was dieses Beispiel macht: Es definiert zwei Klassen: Person (mit den Attributen name, age und der Methode greet) und Employee (mit id, role und der Methode work). Person ist die Oberklasse von Employee (Pfeil mit arrowhead=onormal, UML-Standard für Vererbung). Das \l richtet den Text im Record linksbündig aus.
Professionelle ER-Diagramme mit HTML-Label
Wenn du mit Datenbanken arbeitest, musst du früher oder später das Tabellenschema zeichnen: Primärschlüssel, Fremdschlüssel, 1:N- oder N:N-Beziehungen. Das Entity-Relationship-Diagramm (ER) ist dafür der Standard.
DOT unterstützt HTML-Tabellen in Knoten mit shape=plaintext, sodass du saubere, professionelle ER-Diagramme erstellen kannst. Unverzichtbar ist das für:
Datenbankentwurf: Bevor du Migrationen schreibst, zeichne das Schema. Identifiziere Entitäten, Attribute, Beziehungen. Validiere den Entwurf mit dem Team. Datenmodellierung: Wenn du ein neues Modul entwirfst, beginne mit dem Datenmodell. Das ER-Diagramm hilft dir, über Normalisierung und Performance nachzudenken. Reverse Engineering: Erbst du eine Legacy-DB ohne Dokumentation, erzeuge das ER-Diagramm aus der DB selbst (mit Werkzeugen wie SchemaSpy oder pg_dump + Skript), um die Struktur zu verstehen. Dokumentation: Das ER-Diagramm ist auch für Nicht-Entwickler verständlich (Produktmanager, Business-Analysten).
Nützliche Attribute:
Verwende shape=plaintext, um HTML-Labels zu aktivieren. Verwende das HTML-Element <TABLE>, um strukturierte Kästen mit Kopfzeile (Tabellenname) und Zeilen (Felder) zu erzeugen. Verwende arrowhead=crow für 1:N-Beziehungen (Standard in ER-Diagrammen). Verwende label="1:N" an den Kanten, um die Kardinalität explizit zu machen.
Beispiel:
digraph ER {
node [shape=plaintext];
User [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD><B>User</B></TD></TR>
<TR><TD>id PK</TD></TR>
<TR><TD>email</TD></TR>
</TABLE>
>];
Order [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD><B>Order</B></TD></TR>
<TR><TD>id PK</TD></TR>
<TR><TD>user_id FK</TD></TR>
</TABLE>
>];
User -> Order [label="1:N", arrowhead="crow"];
}
Was dieses Beispiel macht: Es definiert zwei Tabellen (User und Order) mit HTML. Jede Tabelle hat eine fette Kopfzeile und Zeilen für die Felder. Der Pfeil mit arrowhead=crow und label="1:N" zeigt die Beziehung: Ein User hat viele Orders (Fremdschlüssel user_id in Order).
Diagramme von CI/CD-Pipelines
Wenn du in einem Team mit Continuous Integration und Deployment arbeitest, hast du eine Pipeline, die automatische Schritte ausführt: Build, Test, statische Analyse, Packaging, Deploy, Monitoring. Wenn etwas kaputtgeht oder ein neuer Entwickler dazukommt, brauchst du ein Diagramm der gesamten Pipeline.
Das CI/CD-Diagramm zeigt den automatischen Ablauf vom Commit bis zum Deploy. Nützlich ist es für:
DevOps und SRE: Dokumentiere die bestehende Pipeline. Finde die Engpässe (welcher Schritt dauert am längsten?). Onboarding im Team: Ein neuer Entwickler sieht sich das Diagramm an und versteht sofort, was nach einem git push passiert. Optimierung: Willst du einige Schritte parallelisieren? Das Diagramm zeigt dir, welche wovon abhängen. Debugging: Schlägt die Pipeline fehl? Das Diagramm hilft dir zu verstehen, bei welchem Schritt und warum (gestrichelter Pfeil für Wiederholungen).
Nützliche Attribute:
Verwende rankdir=LR für einen horizontalen Ablauf (typisch für Pipelines). Verwende shape=box mit style=filled für die Schritte und färbe sie nach Typ (Build=blau, Test=grün, Deploy=rot). Verwende style=dotted mit label="retry", um automatische Wiederholungsmechanismen zu zeigen. Verwende label an den Kanten, um Bedingungen anzugeben (z. B. “nur auf dem master-Branch”).
Beispiel:
digraph CICD {
graph [rankdir=LR];
node [shape=box, style=filled, fillcolor="#F8FBFF"];
Code -> Build -> Test -> Package -> Deploy -> Monitor;
Test -> Build [style=dotted, label="retry"];
}
Was dieses Beispiel macht: Es zeigt eine klassische Pipeline: Code → Build → Test → Package → Deploy → Monitor. Der gestrichelte Pfeil von Test zu Build zeigt eine automatische Wiederholung, wenn ein Test fehlschlägt. Ein linearer Ablauf, sofort verständlich.
Komplexität reduzieren: Concept Maps und Analyse
Nicht jedes Diagramm muss hierarchisch oder gerichtet sein. Manchmal musst du begriffliche Beziehungen ohne feste Struktur darstellen: beim Brainstorming, beim gemeinsamen Entwurf im Team oder wenn du begriffliche Abhängigkeiten zwischen Technologiebereichen abbilden willst.
Die Concept Map hat keinen “Anfang” und kein “Ende”: Sie ist ein Netz organisch verbundener Knoten. Nützlich ist sie für:
Brainstorming: Beginne bei einer zentralen Idee und füge verbundene Knoten hinzu, während du mit dem Team diskutierst. Die Karte wächst von selbst. Gemeinsamer Entwurf: Bilde in einer Design-Session die Komponenten und ihre Beziehungen ab. Die Hierarchie kennst du noch nicht, aber du weißt, dass “das Backend mit Datenbank und API spricht”. Analyse begrifflicher Abhängigkeiten: Du willst verstehen, welche Technologiebereiche verbunden sind (z. B. Security → Logging → Observability). Übersichtsdokumentation: Für nicht technische Stakeholder ist eine Concept Map zugänglicher als ein hierarchischer Graph.
Nützliche Attribute:
Verwende die Engine neato oder fdp statt dot, um ein organisches Layout auf Basis physikalischer Kräfte zu bekommen. Verwende shape=ellipse für Begriffsknoten (keine Prozesse). Verwende style=filled mit sanften Farben für visuelle Gruppierungen. Verwende ungerichtete Graphen (graph statt digraph), wenn die Beziehungen in beide Richtungen gelten.
Beispiel mit der Engine neato:
graph Concepts {
layout=neato;
node [shape=ellipse, style=filled, fillcolor="#EFEFFF"];
Backend -- Database;
Backend -- API;
API -- Security;
Security -- Logging;
Logging -- Observability;
}
Überlappungen vermeiden: overlap und splines
Eines der häufigsten Probleme beim Zeichnen komplexer Graphen sind Überlappungen von Pfeilen, Text und Knoten. Graphviz bietet gezielte Attribute, um dieses Verhalten zu steuern und die Diagramme lesbarer zu machen.
Das Problem: unerwünschte Überlappungen
Bei vielen Knoten und Pfeilen, besonders mit hierarchischen Layouts oder mit splines=ortho, können Pfeile über die Labels der Cluster oder über Knoten laufen. Hier ein typisches Beispiel des Problems:
digraph OverlapProblem {
graph [rankdir=TB, splines=ortho];
node [shape=box, style=rounded];
subgraph cluster_a {
label="Component A";
A1; A2;
}
subgraph cluster_b {
label="Component B";
B1; B2;
}
subgraph cluster_c {
label="Component C";
C1; C2;
}
A1 -> B1;
A2 -> B2;
B1 -> C1;
B2 -> C2;
A1 -> C1;
}
Problem: Mit splines=ortho können Pfeile die Labels der Cluster kreuzen und das Diagramm unübersichtlich machen.
Die Lösung: overlap und splines
Graphviz bietet mehrere Attribute, um dieses Problem zu lösen:
overlap: Überlappungen zwischen Knoten vermeiden
graph [overlap=false];
Die wichtigsten Optionen:
falseodervoronoi: vermeidet Überlappungen (bessere Qualität, langsamer)scale: skaliert den Graphen, um Überlappungen zu vermeidenscalexy: skaliert mit unterschiedlichen Proportionen auf X und Ytrue(Standard): erlaubt Überlappungen
splines: Form der Kanten steuern
graph [splines=true];
Optionen:
trueoderspline: weiche Kurven, die Knoten ausweichen (empfohlen)curved: leicht gekrümmte Kantenpolyline: gebrochene Linienortho: orthogonale Linien (können Überlappungen verursachen!)lineoderfalse: gerade Linien
sep: zusätzlicher Abstand zwischen Elementen
graph [sep="+0.2"];
Fügt Abstand zwischen Knoten und Kanten hinzu (in Zoll). Das + bedeutet “zum Standardwert hinzufügen”.
ranksep und nodesep: Abstand zwischen Ebenen und Knoten
graph [ranksep=0.8, nodesep=0.6];
Vergrößert den vertikalen (ranksep) und horizontalen (nodesep) Abstand zwischen den Elementen.
Verbessertes Beispiel
Hier derselbe Graph mit optimierten Attributen gegen Überlappungen:
digraph OverlapSolved {
graph [
rankdir=TB,
ranksep=0.8,
nodesep=0.6,
overlap=false,
splines=true,
sep="+0.2"
];
node [shape=box, style=rounded];
subgraph cluster_a {
label="Component A";
style=filled;
fillcolor="#E8F4F8";
A1; A2;
}
subgraph cluster_b {
label="Component B";
style=filled;
fillcolor="#FFF4E6";
B1; B2;
}
subgraph cluster_c {
label="Component C";
style=filled;
fillcolor="#F0F0F0";
C1; C2;
}
A1 -> B1;
A2 -> B2;
B1 -> C1;
B2 -> C2;
A1 -> C1;
}
Ergebnis: Die Pfeile weichen jetzt Knoten und Labels aus, der Graph ist luftiger und lesbarer. Die Hintergrundfarben helfen, die Cluster zu unterscheiden.
Wann du was verwendest
| Szenario | Empfohlene Attribute |
|---|---|
| Komplexe Diagramme mit vielen Knoten | overlap=false, splines=true |
| Hierarchische Graphen (Flussdiagramme, Architekturen) | ranksep=0.8, nodesep=0.6, splines=true |
| Graphen mit Clustern | overlap=false, sep="+0.2" |
| “Architekten”-Diagramme mit geraden Linien | splines=polyline (ortho vermeiden) |
| Kleine, einfache Graphen | Standard (nichts zu ändern) |
Faustregel: Beginne immer mit overlap=false und splines=true, wenn du mehr als 10 Knoten hast oder Cluster verwendest.
Vollständiges Beispiel mit allen Best Practices
Hier ein reales Beispiel, das alle empfohlenen Attribute kombiniert: eine Microservices-Architektur mit 4 Schichten, vielen Knoten und Kanten, farbigen Clustern und optimierten Abständen:
digraph CompleteExample {
graph [
rankdir=TB,
ranksep=1.0,
nodesep=0.7,
overlap=false,
splines=true,
sep="+0.25"
];
node [shape=box, style="rounded,filled", fillcolor="#F0F4FF", fontname="Segoe UI", fontsize=11];
edge [color="#555555", arrowsize=0.8];
subgraph cluster_frontend {
label="Frontend Layer";
style=filled;
fillcolor="#E8F4F8";
color="#5A9FD4";
WebUI [label="Web UI"];
MobileApp [label="Mobile App"];
}
subgraph cluster_api {
label="API Gateway Layer";
style=filled;
fillcolor="#FFF4E6";
color="#E8A87C";
Gateway [label="API Gateway"];
LoadBalancer [label="Load Balancer"];
}
subgraph cluster_services {
label="Microservices Layer";
style=filled;
fillcolor="#F0F8E8";
color="#90C290";
AuthService [label="Auth Service"];
UserService [label="User Service"];
OrderService [label="Order Service"];
PaymentService [label="Payment Service"];
}
subgraph cluster_data {
label="Data Layer";
style=filled;
fillcolor="#F5F5F5";
color="#999999";
UsersDB [shape=cylinder, fillcolor="#D0E8FF", label="Users DB"];
OrdersDB [shape=cylinder, fillcolor="#D0E8FF", label="Orders DB"];
Cache [shape=box, fillcolor="#FFE8D0", label="Redis Cache"];
}
// Frontend zum Gateway
WebUI -> LoadBalancer [label="HTTPS"];
MobileApp -> LoadBalancer [label="HTTPS"];
// Gateway zu den Services
LoadBalancer -> Gateway;
Gateway -> AuthService [label="gRPC"];
Gateway -> UserService [label="REST"];
Gateway -> OrderService [label="REST"];
// Abhängigkeiten zwischen Services
OrderService -> PaymentService [label="API call"];
UserService -> AuthService [label="validate"];
PaymentService -> AuthService [label="validate"];
// Datenzugriff
AuthService -> UsersDB;
UserService -> UsersDB;
UserService -> Cache [style=dashed, label="cache"];
OrderService -> OrdersDB;
OrderService -> Cache [style=dashed, label="cache"];
}
Kommandozeile:
dot -Tsvg overlap_complete.dot -o overlap_complete.svg
Was dieses Beispiel zeigt:
- overlap=false: keine Überlappungen zwischen Knoten, selbst mit 13 Knoten und 4 Clustern
- splines=true: geschwungene Pfeile, die Knoten und Labels elegant ausweichen
- sep="+0.25": zusätzlicher Abstand, der alles lesbar hält
- ranksep=1.0, nodesep=0.7: großzügige Abstände zwischen Schichten und Knoten
- Farbige Cluster: Jede Schicht hat eine eigene Farbe und ist sofort erkennbar
- Labels an den Kanten: Protokolle (HTTPS, gRPC, REST) und Verbindungsart explizit
- Gestrichelter Stil für den Cache: optionale Abhängigkeiten anders dargestellt
- Zylinderform für DBs: Datenbanken sofort erkennbar
Das ist die ideale Vorlage, um komplexe Architekturen professionell und lesbar zu dokumentieren.
Color Schemes: professionelle Paletten, sofort einsatzbereit
Graphviz enthält vordefinierte Color Schemes auf Basis der professionellen Paletten von ColorBrewer. Statt die Farben von Hand auszuwählen, kannst du Paletten verwenden, die auf Lesbarkeit, Barrierefreiheit und professionelle Wirkung getestet sind.
Wie Color Schemes funktionieren
Mit dem Attribut colorscheme wählst du eine Palette und verwendest dann statt Hex-Codes die Zahlen 1-9 (oder mehr, je nach Schema):
node [colorscheme=set39, fillcolor=1, color=2];
Die Color Schemes sind in Kategorien gegliedert:
- Qualitativ (set1, set2, set3, pastel1, pastel2, dark2, paired, accent): für unterschiedliche Kategorien
- Sequenziell (blues3-9, greens3-9, reds3-9, purples3-9, oranges3-9): für aufsteigende Werte
- Divergierend (rdylgn3-11, spectral3-11, rdbu3-11): für Daten mit einem Mittelpunkt
Vollständige Referenz: graphviz.org/docs/attrs/colorscheme/
Praxisbeispiele mit professionellen Color Schemes
Jedes Beispiel verwendet dasselbe Diagramm (einen Prozess in 5 Schritten), aber mit unterschiedlichen Paletten. Vergleiche sie und wähle die, die am besten zu deinem Anwendungsfall passt.
Beispiel 1: Set39 (qualitativ, lebhaft)
Hervorragend, um verschiedene Kategorien auseinanderzuhalten, für farbige Präsentationen und Dashboards.
digraph ProcessSet39 {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=set39, fontname=Arial];
edge [colorscheme=set39, penwidth=2];
Start [fillcolor=1, label="Start"];
Validate [fillcolor=2, label="Validate"];
Process [fillcolor=3, label="Process"];
Store [fillcolor=4, label="Store"];
Notify [fillcolor=5, label="Notify"];
Start -> Validate [color=1];
Validate -> Process [color=2];
Process -> Store [color=3];
Store -> Notify [color=4];
}
Kommandozeile:
dot -Tsvg colorscheme_set39.dot -o colorscheme_set39.svg
Beispiel 2: Pastel19 (qualitativ, sanft)
Pastellfarben für technische Dokumentation, Wikis, Blogartikel. Weniger auffällig, aber auf Dauer angenehmer zu lesen.
digraph ProcessPastel {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=pastel19, fontname=Arial, fontcolor="#333333"];
edge [colorscheme=dark28, penwidth=2];
Start [fillcolor=1, label="Start"];
Validate [fillcolor=3, label="Validate"];
Process [fillcolor=5, label="Process"];
Store [fillcolor=7, label="Store"];
Notify [fillcolor=9, label="Notify"];
Start -> Validate [color=1];
Validate -> Process [color=3];
Process -> Store [color=5];
Store -> Notify [color=7];
}
Kommandozeile:
dot -Tsvg colorscheme_pastel.dot -o colorscheme_pastel.svg
Beispiel 3: Blues9 (sequenziell, Abstufung)
Ideal, um zunehmende Intensität, Prioritäten oder Reifegrade zu zeigen.
digraph ProcessBlues {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=blues9, fontname=Arial];
edge [color="#2171B5", penwidth=2];
Start [fillcolor=2, fontcolor=black, label="Start"];
Validate [fillcolor=4, fontcolor=white, label="Validate"];
Process [fillcolor=6, fontcolor=white, label="Process"];
Store [fillcolor=8, fontcolor=white, label="Store"];
Notify [fillcolor=9, fontcolor=white, label="Notify"];
Start -> Validate -> Process -> Store -> Notify;
}
Kommandozeile:
dot -Tsvg colorscheme_blues.dot -o colorscheme_blues.svg
Beispiel 4: RdYlGn9 (divergierend, Ampel)
Perfekt für Zustände wie Erfolg/Warnung/Fehler, Health Checks, Monitoring.
digraph ProcessStatus {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=rdylgn9, fontname=Arial, fontcolor=black];
edge [penwidth=2, color="#666666"];
Idle [fillcolor=5, label="Idle\n(neutral)"];
Starting [fillcolor=7, label="Starting\n(ok)"];
Running [fillcolor=9, label="Running\n(good)"];
Warning [fillcolor=4, label="Warning"];
Error [fillcolor=1, label="Error"];
Idle -> Starting -> Running;
Running -> Warning [style=dashed];
Warning -> Error [style=dashed];
Running -> Idle [label="stop"];
}
Kommandozeile:
dot -Tsvg colorscheme_rdylgn.dot -o colorscheme_rdylgn.svg
Beispiel 5: Paired12 (qualitativ, Paare)
Verwendet aufeinander abgestimmte Farbpaare. Hervorragend für Vergleiche, A/B-Versionen, Beziehungen.
digraph ProcessPaired {
graph [rankdir=TB, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=paired12, fontname=Arial];
edge [colorscheme=paired12, penwidth=2];
subgraph cluster_v1 {
label="Version 1.x";
style=filled;
fillcolor="#F0F0F0";
V1_Start [fillcolor=1, label="Start v1"];
V1_Process [fillcolor=1, label="Process v1"];
V1_End [fillcolor=1, label="End v1"];
V1_Start -> V1_Process -> V1_End;
}
subgraph cluster_v2 {
label="Version 2.x";
style=filled;
fillcolor="#F8F8F8";
V2_Start [fillcolor=2, label="Start v2"];
V2_Process [fillcolor=2, label="Process v2"];
V2_End [fillcolor=2, label="End v2"];
V2_Start -> V2_Process -> V2_End;
}
V1_Start -> V2_Start [label="upgrade", color=4, style=dashed];
}
Kommandozeile:
dot -Tsvg colorscheme_paired.dot -o colorscheme_paired.svg
Beispiel 6: Accent8 (qualitativ, starke Kontraste)
Maximaler Kontrast zwischen den Elementen. Um wichtige Unterschiede hervorzuheben.
digraph ProcessAccent {
graph [rankdir=LR, bgcolor="#F5F5F5"];
node [shape=box, style="rounded,filled", colorscheme=accent8, fontname=Arial, fontcolor=black];
edge [colorscheme=accent8, penwidth=2];
Input [fillcolor=1, label="Input"];
Parse [fillcolor=2, label="Parse"];
Transform [fillcolor=3, label="Transform"];
Validate [fillcolor=4, label="Validate"];
Output [fillcolor=5, label="Output"];
Input -> Parse [color=1];
Parse -> Transform [color=2];
Transform -> Validate [color=3];
Validate -> Output [color=4];
Validate -> Parse [color=6, label="retry", style=dashed];
}
Kommandozeile:
dot -Tsvg colorscheme_accent.dot -o colorscheme_accent.svg
Wann du welches Color Scheme verwendest
| Szenario | Empfohlenes Color Scheme |
|---|---|
| Unterschiedliche Kategorien, Präsentationen | set39, set28, dark28 |
| Technische Dokumentation, Wikis | pastel19, pastel28 |
| Abstufungen, Prioritäten, Stufen | blues9, greens9, purples9, oranges9 |
| Zustände (ok/warning/error) | rdylgn9, rdylbu9, spectral9 |
| Vergleiche, A/B-Versionen | paired12, paired11 |
| Maximaler Kontrast | accent8, set39 |
| Barrierefreiheit (Farbenblindheit) | set2, dark2 (ColorBrewer safe) |
Color Schemes kombinieren
Du kannst für Knoten und Kanten unterschiedliche Schemata verwenden:
node [colorscheme=pastel19, fillcolor=3];
edge [colorscheme=dark28, color=2];
Tipp: Prüfe die Farben immer mit ColorBrewer, um Barrierefreiheit und Druckbarkeit sicherzustellen.
Fortgeschrittene Techniken: Ports, Ranks, Compound Edges
Ports in Records: Verbinde Kanten mit bestimmten Feldern eines Records über die Syntax node:port:
ClassA:field1 -> ClassB:field2;
Knoten auf dieselbe Ebene zwingen: Mit rank=same positionierst du mehrere Knoten auf derselben horizontalen Linie:
{ rank=same; A; B; C; }
Compound Edges zwischen Clustern: Verbinde ganze Cluster statt einzelner Knoten mit lhead und ltail:
edge [lhead=cluster_B, ltail=cluster_A];
Orthogonale Kanten: Kanten mit rechten Winkeln für einen “Architekten”-Stil:
graph [splines=ortho];
Professioneller Stil: praktische Tipps
- Verwende stimmige Paletten.
- Vermeide zu grelle Farbverläufe.
- Verwende
Inter,ArialoderRobotofür gute Lesbarkeit. - Verwende
orthofür “Architekten”-Kanten. - Halte angemessene Abstände ein (
nodesep,ranksep). - Bevorzuge SVG für die Qualität in Blogs.
- Halte die DOT-Dateien unter Versionskontrolle.
Grafikstile, sofort einsatzbereit
Hier sind 5 Stilvarianten für dasselbe Zustandsdiagramm, bereit zum Kopieren und Anpassen an deine Diagramme. Jeder Stil legt Farben, Schriften, Größen und Formen fest und sorgt für einen einheitlichen Look.
Stil 1: Corporate Blue (professionell, formell)
Blau-graue Palette, Schrift Arial, aufgeräumter Stil für Unternehmenspräsentationen.
digraph CorporateBlue {
graph [
rankdir=LR,
bgcolor="#F8F9FA",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#E3F2FD",
color="#1976D2",
fontname="Segoe UI",
fontsize=11,
fontcolor="#1565C0",
penwidth=2
];
edge [
color="#1976D2",
fontname="Segoe UI",
fontsize=10,
fontcolor="#424242"
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Kommandozeile:
dot -Tsvg style_corporate.dot -o style_corporate.svg
Stil 2: Dark Mode (modern, technisch)
Dunkler Hintergrund, heller Text, grün-cyanfarbene Palette für moderne UIs und Entwicklerwerkzeuge.
digraph DarkMode {
graph [
rankdir=LR,
bgcolor="#1E1E1E",
fontname="Consolas",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#2D2D30",
color="#00D9FF",
fontname="Consolas",
fontsize=11,
fontcolor="#E0E0E0",
penwidth=2
];
edge [
color="#00D9FF",
fontname="Consolas",
fontsize=10,
fontcolor="#B0B0B0"
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Kommandozeile:
dot -Tsvg style_dark.dot -o style_dark.svg
Stil 3: Warm Minimal (sanft, gut lesbar)
Warme Orange-Beige-Palette, serifenlose Schrift, hervorragend für technische Dokumentation.
digraph WarmMinimal {
graph [
rankdir=LR,
bgcolor="#FFFBF5",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#FFE8CC",
color="#FF8C42",
fontname="Segoe UI",
fontsize=11,
fontcolor="#6B4423",
penwidth=1.5
];
edge [
color="#FF8C42",
fontname="Segoe UI",
fontsize=10,
fontcolor="#8B5A3C",
penwidth=1.5
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Kommandozeile:
dot -Tsvg style_warm.dot -o style_warm.svg
Stil 4: Monochrome (elegant, druckfreundlich)
Schwarz-weiß mit Graustufen, perfekt für den Druck und formelle Dokumentation.
digraph Monochrome {
graph [
rankdir=LR,
bgcolor="white",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#F5F5F5",
color="#333333",
fontname="Segoe UI",
fontsize=11,
fontcolor="#000000",
penwidth=2
];
edge [
color="#333333",
fontname="Segoe UI",
fontsize=10,
fontcolor="#666666",
penwidth=1.5
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Kommandozeile:
dot -Tsvg style_mono.dot -o style_mono.svg
Stil 5: Vibrant Gradient (kreativ, auffällig)
Lebhafte Farben mit Farbverläufen, hervorragend für Präsentationen und optisch ansprechende Folien.
digraph VibrantGradient {
graph [
rankdir=LR,
bgcolor="#FAFAFA",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#A8E6CF:#56CCF2",
gradientangle=90,
color="#2D6A9F",
fontname="Segoe UI",
fontsize=11,
fontcolor="#1A3A52",
penwidth=2.5
];
edge [
color="#9B59B6",
fontname="Segoe UI",
fontsize=10,
fontcolor="#5B3A72",
penwidth=2
];
Idle [label="Idle"];
Processing [label="Processing", fillcolor="#FFD93D:#FF6B9D", gradientangle=90];
Complete [label="Complete", fillcolor="#6BCF7F:#4ECDC4", gradientangle=90];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Kommandozeile:
dot -Tsvg style_vibrant.dot -o style_vibrant.svg
So verwendest du diese Stile
Kopiere den Block graph, node, edge des Stils, der dir gefällt, und wende ihn auf deine Diagramme an. Anpassen kannst du dann:
- Farben: Ersetze die Hex-Codes durch deine Palette
- Schriften: Verwende
fontname="FontName"(Arial, Helvetica, Courier, Times, Verdana, Consolas) - Größen:
fontsizefür den Text,penwidthfür die Stärke von Rändern und Pfeilen - Form:
box,ellipse,circle,diamond,cylinder,record - Farbverläufe: Verwende
fillcolor="color1:color2"mitgradientangle(nur bei manchen Ausgabeformaten)
Hinweise zur Schriftkompatibilität
Die Schriften müssen auf dem System installiert sein, auf dem du die Bilder erzeugst:
- Universelle Schriften (funktionieren überall):
Arial,Helvetica,Times,Times-Roman,Courier - Moderne Schriften (Verfügbarkeit prüfen):
Verdana,Consolas,Roboto,Inter - Windows: Die meisten Schriften sind bereits installiert
- macOS: Hervorragende Unterstützung für die Standardschriften
- Linux: Installiere
fonts-liberationoderfonts-dejavu, um Entsprechungen zu Arial/Helvetica zu haben - CI/CD: Verwende Basisschriften oder nimm die Schriften in den Docker-Container auf
Ist eine Schrift nicht verfügbar, greift Graphviz auf einen Fallback zurück (meist Times). Um sicherzugehen, verwende immer Basisschriften oder teste die Erzeugung in der Produktionsumgebung.
Workflow: Graphviz in die echte Arbeit integrieren
Lege die
.gv-Dateien ins Repository.Erzeuge die SVGs automatisch in der CI:
dot -Tsvg diagram.gv -o diagram.svgBinde die SVGs in die Dokumentation ein (README, Wiki, Blog).
Aktualisiere die Diagramme bei jedem Refactoring.
Nutze Diff und Versionierung der DOT-Dateien wie beim Code.
Troubleshooting: häufige Fehler und Lösungen
Fehler: “syntax error in line X near…”
- Ursache: Ungültige DOT-Syntax
- Lösung: Prüfe auf fehlende Semikolons, nicht geschlossene Klammern, nicht passende Anführungszeichen
- Beispiel:
A -> Bmuss mit;enden →A -> B;
Fehler: “Warning: Unable to find font…”
- Ursache: Die angegebene Schrift ist auf dem System nicht installiert
- Lösung: Verwende universelle Schriften (Arial, Helvetica, Times) oder installiere die benötigte Schrift
- Verfügbare Schriften prüfen:
dot -vzeigt die verfügbaren Schriften
Das Diagramm ist zu groß/klein
- Lösung 1: Füge
graph [size="8,6"]hinzu, um die Abmessungen zu begrenzen (in Zoll) - Lösung 2: Verwende
graph [ratio=compress], um automatisch zu komprimieren - Lösung 3: Erzeuge ein PNG mit eigener DPI:
dot -Tpng -Gdpi=150 file.dot -o file.png
Pfeile überlappen Knoten
- Lösung: Füge
graph [overlap=false, splines=true]hinzu (siehe Abschnitt “Überlappungen vermeiden”)
Die Knoten sind alle horizontal statt vertikal ausgerichtet
- Lösung: Verwende
graph [rankdir=TB]für oben nach unten (Standard ist LR = links nach rechts)
Der Cluster erscheint nicht
- Ursache: Der Name des Clusters beginnt nicht mit
cluster_ - Lösung: Benenne
subgraph mygroupinsubgraph cluster_mygroupum
SVG-Ausgabe zu groß (Dateigröße)
- Ursache: SVG mit vielen Elementen
- Lösung 1: Verwende PNG statt SVG für sehr komplexe Graphen
- Lösung 2: Optimiere mit
svgo:svgo input.svg -o output.svg
Der Graph wird nicht erzeugt (keine Ausgabe, kein Fehler)
- Ursache: Falscher Befehl oder falsche Umleitung
- Prüfen: Verwende
-vfür die ausführliche Ausgabe:dot -v -Tsvg input.dot -o output.svg - Schnelltest:
echo "digraph{A->B}" | dot -Tsvg > test.svg
Die Labels der Kanten sind nicht sichtbar
- Ursache: Labels zu lang oder Schrift zu klein
- Lösung: Erhöhe
fontsizean den Kanten oder verwende\n, um die Labels auf mehrere Zeilen umzubrechen
Best Practices für sauberen DOT-Code
Don’t Repeat Yourself (DRY)
Definiere Attribute einmal auf oberster Ebene, statt sie bei jedem Element zu wiederholen.
❌ Schlecht (repetitiv):
digraph {
node [fontname="Segoe UI"];
A [fontname="Segoe UI", shape=box];
B [fontname="Segoe UI", shape=box];
C [fontname="Segoe UI", shape=box];
}
✅ Gut (DRY):
digraph {
// Einmal definieren, gilt für alle
graph [fontname="Segoe UI"];
node [fontname="Segoe UI", shape=box];
edge [fontname="Segoe UI"];
A; B; C; // Erben alle Attribute
}
Grundprinzip: Verwende die Deklarationen graph, node und edge, um Standardwerte zu setzen. Überschreibe sie nur, wenn ein bestimmtes Element andere Attribute braucht.
Kommentare verwenden
Füge Kommentare hinzu, um komplexe Abschnitte zu erklären:
digraph {
// Globales Styling
graph [rankdir=LR, fontname="Segoe UI"];
// Kernkomponenten
A -> B;
// Pfad der Fehlerbehandlung
B -> Error [style=dashed, color=red];
}
Große Graphen organisieren
Gruppiere zusammengehörige Deklarationen:
digraph {
// === Konfiguration ===
graph [rankdir=TB];
node [shape=box];
// === Services ===
ServiceA; ServiceB; ServiceC;
// === Datenbanken ===
DB1 [shape=cylinder];
DB2 [shape=cylinder];
// === Verbindungen ===
ServiceA -> DB1;
ServiceB -> DB2;
}
DOT-Vorlagen + Graphviz-Befehle (CLI)
Jede Vorlage enthält:
das DOT-Snippet
den CLI-Befehl zum Erzeugen des Bildes
Der Einheitlichkeit halber verwende ich das Format SVG, aber du kannst -Tsvg ersetzen durch:
-Tpng-Tpdf-Tjpg-Tgif
Den DOT-Input kannst du in template.dot speichern oder per Pipe übergeben.
Flussdiagramm
Vorlage 1: Einfacher Prozess
digraph FlowBasic {
graph [rankdir=TB];
node [shape=rectangle, style=rounded, fontsize=12];
Start [label="Start", shape=circle];
Step1 [label="Input validation"];
Step2 [label="Process request"];
Step3 [label="Persist data"];
End [label="End", shape=doublecircle];
Start -> Step1 -> Step2 -> Step3 -> End;
}
Kommandozeile:
dot -Tsvg FlowBasic.dot -o FlowBasic.svg
Vorlage 2: Verzweigung (if/else)
digraph FlowIfElse {
graph [rankdir=TB];
node [fontsize=12, style=rounded];
Start [shape=circle];
Check [shape=diamond, label="Is valid?"];
A [label="Handle valid case"];
B [label="Handle error"];
End [shape=doublecircle];
Start -> Check;
Check -> A [label="Yes"];
Check -> B [label="No"];
A -> End;
B -> End;
}
Kommandozeile:
dot -Tsvg FlowIfElse.dot -o FlowIfElse.svg
Vorlage 3: Prozess mit Abschnitten
digraph FlowSections {
graph [rankdir=TB];
node [fontsize=11, style=rounded];
subgraph cluster_input {
label="Input Stage";
color=lightgrey;
style=filled;
A1 [label="Receive request"];
A2 [label="Validate payload"];
A1 -> A2;
}
subgraph cluster_processing {
label="Processing Stage";
color=lightblue;
style=filled;
P1 [label="Transform data"];
P2 [label="Apply business rules"];
P1 -> P2;
}
subgraph cluster_output {
label="Output Stage";
color=lightyellow;
style=filled;
O1 [label="Persist"];
O2 [label="Return response"];
O1 -> O2;
}
A2 -> P1 -> O1;
}
Kommandozeile:
dot -Tsvg FlowSections.dot -o FlowSections.svg
Zustandsautomat
Vorlage 4: Einfacher Zustandsautomat
digraph StateMachine {
graph [rankdir=LR];
node [shape=circle, fontsize=12];
Idle;
Loading;
Error;
Success;
Idle -> Loading [label="start"];
Loading -> Success [label="ok"];
Loading -> Error [label="fail"];
Error -> Idle [label="retry"];
}
Kommandozeile:
dot -Tsvg StateMachine.dot -o StateMachine.svg
Vorlage 5: Verschachtelte Zustände
digraph NestedStates {
graph [rankdir=LR];
node [fontsize=11];
subgraph cluster_ready {
label="Ready state";
style=dashed;
R1 [shape=circle, label="Idle"];
R2 [shape=circle, label="Primed"];
R1 -> R2 [label="prepare"];
}
subgraph cluster_active {
label="Active state";
style=dashed;
A1 [shape=circle, label="Running"];
A2 [shape=circle, label="Paused"];
A1 -> A2 [label="pause"];
A2 -> A1 [label="resume"];
}
R2 -> A1 [label="activate"];
}
Kommandozeile:
dot -Tsvg NestedStates.dot -o NestedStates.svg
Sequenzdiagramm (DOT)
Vorlage 6: Horizontale Sequenz
digraph Sequence {
graph [rankdir=LR];
node [shape=box, fontsize=11];
Client -> API [label="POST /login"];
API -> AuthService [label="Check credentials"];
AuthService -> DB [label="Query user"];
DB -> AuthService [label="Result"];
AuthService -> API [label="Token"];
API -> Client [label="200 OK"];
}
Kommandozeile:
dot -Tsvg Sequence.dot -o Sequence.svg
Vorlage 7: Sequenz mit Aktivierungen
digraph SequenceActivation {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
User -> Frontend [label="Login"];
Frontend -> Backend [label="POST /login"];
Backend -> Backend [label="validate()"];
Backend -> DB [label="SELECT user"];
DB -> Backend [label="row found"];
Backend -> Frontend [label="JWT"];
Frontend -> User [label="Welcome"];
}
Kommandozeile:
dot -Tsvg SequenceActivation.dot -o SequenceActivation.svg
Abhängigkeitsgraph
Vorlage 8: Module
digraph DependencyTree {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=12];
App -> ModuleA;
App -> ModuleB;
ModuleA -> LibA;
ModuleA -> LibB;
ModuleB -> LibB;
}
Kommandozeile:
dot -Tsvg DependencyTree.dot -o DependencyTree.svg
Vorlage 9: Microservices
digraph MicroservicesDep {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
Gateway -> Auth;
Gateway -> Orders;
Auth -> UsersDB;
Orders -> ProductsService;
Orders -> Payments;
Payments -> BankAPI;
}
Kommandozeile:
dot -Tsvg MicroservicesDep.dot -o MicroservicesDep.svg
Architekturdiagramm
Vorlage 10: Schichten
digraph Layered {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=12];
subgraph cluster_presentation {
label="Presentation Layer";
style=filled;
color=lightyellow;
UI;
API;
}
subgraph cluster_business {
label="Business Layer";
style=filled;
color=lightblue;
Services;
}
subgraph cluster_data {
label="Data Layer";
style=filled;
color=lightgrey;
DB;
Cache;
}
UI -> API -> Services -> DB;
Services -> Cache;
}
Kommandozeile:
dot -Tsvg Layered.dot -o Layered.svg
Vorlage 11: Hexagonal
digraph Hexagonal {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
AppCore [label="Core Domain"];
PortIn [label="Inbound Ports"];
PortOut [label="Outbound Ports"];
AdapterIn [label="Inbound Adapters"];
AdapterOut [label="Outbound Adapters"];
DB [label="Database"];
UI [label="Frontend/UI"];
UI -> AdapterIn -> PortIn -> AppCore;
AppCore -> PortOut -> AdapterOut -> DB;
}
Kommandozeile:
dot -Tsvg Hexagonal.dot -o Hexagonal.svg
ER-Diagramme
Vorlage 12: 1:N
digraph ER_OneToMany {
graph [rankdir=LR];
node [shape=record, fontsize=11];
User [label="{User|id PK|name|email}"];
Order [label="{Order|id PK|user_id FK|total}"];
User -> Order [label="1:N"];
}
Kommandozeile:
dot -Tsvg ER_OneToMany.dot -o ER_OneToMany.svg
Vorlage 13: N:N
digraph ER_ManyToMany {
graph [rankdir=LR];
node [shape=record, fontsize=11];
Student [label="{Student|id PK|name}"];
Course [label="{Course|id PK|title}"];
Enroll [label="{Enroll|student_id FK|course_id FK}"];
Student -> Enroll;
Course -> Enroll;
}
Kommandozeile:
dot -Tsvg ER_ManyToMany.dot -o ER_ManyToMany.svg
Call Graph
Vorlage 14: Einfach
digraph CallGraph {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=11];
main -> init;
main -> loadConfig;
loadConfig -> readFile;
readFile -> parseJson;
}
Kommandozeile:
dot -Tsvg CallGraph.dot -o CallGraph.svg
Vorlage 15: Mit Kategorien
digraph CategorizedCalls {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=11];
subgraph cluster_io {
label="I/O Functions";
color=lightgrey;
readFile;
writeFile;
}
subgraph cluster_logic {
label="Business Logic";
color=lightblue;
compute;
validate;
}
main -> compute -> validate;
compute -> readFile;
validate -> writeFile;
}
Kommandozeile:
dot -Tsvg CategorizedCalls.dot -o CategorizedCalls.svg
Netzwerkdiagramm
Vorlage 16: Einfach
digraph Network {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
Client -> LoadBalancer;
LoadBalancer -> AppServer1;
LoadBalancer -> AppServer2;
AppServer1 -> DB;
AppServer2 -> DB;
}
Kommandozeile:
dot -Tsvg Network.dot -o Network.svg
Vorlage 17: Mit Protokollen
digraph NetworkProto {
graph [rankdir=LR];
node [shape=box, fontsize=11];
Client -> API [label="HTTPS"];
API -> Auth [label="gRPC"];
API -> Orders [label="REST"];
Orders -> DB [label="TCP"];
}
Kommandozeile:
dot -Tsvg NetworkProto.dot -o NetworkProto.svg
Timeline / Roadmap
Vorlage 18: Timeline
digraph Timeline {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
Start -> Milestone1 -> Milestone2 -> Milestone3 -> Release;
}
Kommandozeile:
dot -Tsvg Timeline.dot -o Timeline.svg
Vorlage 19: Roadmap
digraph Roadmap {
graph [rankdir=LR];
node [shape=box, fontsize=11];
subgraph cluster_backend {
label="Backend";
B1 [label="Auth module"];
B2 [label="Payments"];
}
subgraph cluster_frontend {
label="Frontend";
F1 [label="Login UI"];
F2 [label="Dashboard"];
}
B1 -> B2;
F1 -> F2;
}
Kommandozeile:
dot -Tsvg Roadmap.dot -o Roadmap.svg
Mindmap
Vorlage 20: Mindmap
graph MindMap {
layout=twopi;
rankdir=LR;
node [shape=box, style=rounded, fontsize=11];
Central -- Idea1;
Central -- Idea2;
Central -- Idea3;
Idea2 -- Sub1;
Idea2 -- Sub2;
}
Kommandozeile:
dot -Ktwopi -Tsvg MindMap.dot -o MindMap.svg
Komponentendiagramm
Vorlage 21: Komponenten
digraph Components {
graph [rankdir=LR];
node [shape=component, fontsize=11];
UI -> API;
API -> Service;
Service -> DB;
}
Kommandozeile:
dot -Tsvg Components.dot -o Components.svg
Klassendiagramm
Vorlage 22: UML-ähnliche Klassen
digraph Classes {
graph [rankdir=TB];
node [shape=record, fontsize=11];
Person [label="{Person|name:string|age:int}"];
Student [label="{Student|grade:int}"];
Person -> Student;
}
Kommandozeile:
dot -Tsvg Classes.dot -o Classes.svg
Layouts
Vorlage 23: Horizontal
digraph Horizontal {
graph [rankdir=LR];
node [shape=box, style=rounded];
}
Kommandozeile:
dot -Tsvg Horizontal.dot -o Horizontal.svg
Vorlage 24: Vertikal
digraph Vertical {
graph [rankdir=TB];
node [shape=box, style=rounded];
}
Kommandozeile:
dot -Tsvg Vertical.dot -o Vertical.svg
Vorlage 25: Kreisförmig
graph Circular {
layout=circo;
node [shape=box, style=rounded];
}
Kommandozeile:
dot -Kcirco -Tsvg Circular.dot -o Circular.svg
Professionelle Stile
Vorlage 26: Modernes Theme
digraph Modern {
graph [rankdir=LR];
node [
shape=box,
style="rounded,filled",
fillcolor="#eef3f8",
color="#6a8bbf",
fontsize=11
];
edge [color="#6a8bbf"];
A -> B -> C;
}
Kommandozeile:
dot -Tsvg Modern.dot -o Modern.svg
Vorlage 27: Dark Theme
digraph Dark {
bgcolor="#1e1e1e";
node [
shape=box,
style="rounded,filled",
fillcolor="#333333",
fontcolor="white",
color="#777777",
fontsize=11
];
edge [color="#999999"];
A -> B -> C;
}
Kommandozeile:
dot -Tsvg Dark.dot -o Dark.svg
Nützliche Ressourcen
Offizielle Dokumentation
- Graphviz-Homepage: graphviz.org: offizielle Seite mit Downloads, Dokumentation und Neuigkeiten
- Spezifikation der DOT-Sprache: graphviz.org/doc/info/lang.html: vollständige Referenz der DOT-Syntax
- Galerie der Knotenformen: graphviz.org/doc/info/shapes.html: vollständiger Katalog aller verfügbaren Formen
- Attribut-Referenz: graphviz.org/doc/info/attrs.html: vollständige Liste aller Attribute mit Beschreibungen
- Farbnamen: graphviz.org/doc/info/colors.html: vordefinierte Farbpaletten und unterstützte Codes
Online-Werkzeuge
- GraphvizOnline: dreampuf.github.io/GraphvizOnline: Online-Editor mit Vorschau in Echtzeit
- Edotor: edotor.net: Online-Editor für Graphviz mit Beispielen und Syntax-Highlighting
- WebGraphviz: webgraphviz.com: SVG/PNG-Generator im Browser, ohne Installation
Integrationen und Bibliotheken
- Graphviz Visual Editor (VSCode): Erweiterung für die Live-Vorschau in Visual Studio Code
- PlantUML: plantuml.com: verwendet Graphviz für das UML-Rendering
- Mermaid: mermaid.js.org: JavaScript-basierte Alternative zu Graphviz für Graphen in Markdown
- Python graphviz: graphviz.readthedocs.io: Python-Bibliothek, um Graphen programmatisch zu erzeugen
- Go graphviz: github.com/goccy/go-graphviz: Go-Binding für Graphviz
Galerie und Beispiele
- Graphviz Gallery: graphviz.org/gallery: offizielle Beispiele komplexer Graphen
- GitHub Awesome Graphviz: github.com/topics/graphviz: Repositories und Projekte, die Graphviz verwenden
Community und Support
- Stack Overflow: Tag graphviz: Fragen und Antworten der Community
- Reddit r/graphviz: reddit.com/r/graphviz: Diskussionen, Beispiele und Hilfe
Ergänzende Werkzeuge
- dot2tex: dot2tex.readthedocs.io: wandelt DOT in LaTeX/TikZ um
- SVGO: github.com/svg/svgo: SVG-Optimierer zur Verkleinerung der Dateien
- Inkscape: inkscape.org: Vektoreditor für die manuelle Nachbearbeitung von SVGs
FAQ: häufige Fragen zu DOT und Graphviz
Wie erstelle ich ein Diagramm mit Graphviz?
Lege eine Datei mit der Endung .dot an, die die Beschreibung des Graphen enthält, und führe dann dot -Tsvg file.dot -o output.svg aus. Der Befehl erzeugt aus dem DOT-Code ein SVG-Bild.
Was ist der Unterschied zwischen digraph und graph in DOT?
digraph erzeugt einen gerichteten Graphen (mit Pfeilen), graph einen ungerichteten Graphen (mit Linien ohne Pfeilspitzen). Verwende -> für gerichtete Kanten, -- für ungerichtete.
Wie ändere ich die Layoutrichtung in Graphviz?
Verwende das Attribut rankdir: TB (oben nach unten, Standard), BT (unten nach oben), LR (links nach rechts), RL (rechts nach links). Beispiel: graph [rankdir=LR];
Wie erstelle ich in DOT ein Flussdiagramm mit Entscheidungsrauten?
Verwende shape=diamond für die Entscheidungsknoten: Decision [shape=diamond, label="Valid?"];
Wie gruppiere ich Knoten in Graphviz in einem Kasten (Cluster)?
Verwende subgraph cluster_name { ... }. Das Präfix cluster_ ist Pflicht, damit die Gruppierung angezeigt wird.
Wie erstelle ich ER-Diagramme (Entity-Relationship) mit DOT?
Verwende shape=plaintext mit HTML-Labels für strukturierte Tabellen und arrowhead=crow für 1:N-Beziehungen.
Wie vermeide ich in Graphviz Überlappungen zwischen Pfeilen und Knoten?
Füge graph [overlap=false, splines=true, sep="+0.2"]; hinzu, um Kollisionen zu vermeiden.
Welche Layout-Engine ist die beste für mein Diagramm?
- dot: Flussdiagramme, Pipelines, Hierarchien (Standard)
- neato/fdp: ungerichtete Graphen, Concept Maps
- circo: Hub-and-Spoke-Strukturen
- twopi: radiale Bäume, Organigramme
Wie erzeuge ich mit Graphviz PNG statt SVG?
Ändere das Flag -T: dot -Tpng file.dot -o output.png. Du kannst auch die DPI angeben: dot -Tpng -Gdpi=150.
Kann ich Graphviz online verwenden, ohne es zu installieren?
Ja! Verwende edotor.net oder GraphvizOnline, um DOT-Code im Browser zu testen.
Wie integriere ich Graphviz in meine CI/CD-Pipeline?
Installiere Graphviz in deiner CI-Umgebung (z. B. apt install graphviz in Docker) und füge dann einen Schritt hinzu, der dot -Tsvg *.dot ausführt. Versioniere die .dot-Dateien und erzeuge die Bilder automatisch.
Wie erstelle ich Zustandsdiagramme (Zustandsautomaten) mit DOT?
Verwende shape=circle für die Zustände, shape=point für den Anfangszustand und shape=doublecircle für den Endzustand. Beschrifte die Kanten mit den Ereignissen: Idle -> Loading [label="start"];
Wie wende ich denselben Stil auf mehrere Knoten an, ohne ihn zu wiederholen?
Liste die Knoten in derselben Zeile auf, gefolgt von den Attributen: A; B; C [shape=box, fillcolor=lightblue, style=filled];
Unterstützt DOT HEX-Farben?
Ja! Verwende HEX-Codes wie fillcolor="#E3F2FD" oder vordefinierte Namen wie fillcolor=lightblue.
Wie erstelle ich UML-Diagramme mit Graphviz?
Verwende shape=record für Klassendiagramme: Class [label="{ClassName|attribute:type|method()}"];. Für vollständiges UML lohnt sich ein Blick auf PlantUML, das intern Graphviz verwendet.
Artikel von Daniele Teti, danieleteti.it
Comments