CLI-Adventskalender, Tag 17: dot

CLI-Adventskalender: dot

Avatar von Eric

Heute machen wir einen dot … Punkt. Einen Wichtigen. Aber lasst euch überraschen, was sich hinter dem siebzehnten Türchen des Adventskalenders verbirgt.

Ein klassischer Schock für Informatikstudenten ist ja, dass sie sich neun Semester hart mit Theorie und praktischer Expertise beschäftigen, nur um dann im Berufsalltag herauzufinden, dass die Hälfte ihres Jobs Softskills sind. Nicht-technische Personen müssen abgeholt, Anforderungen erfasst und Teams (plural) koordiniert werden. Neben zwischenmenschlichen, emotionalen Themen, kommt man in der Entwicklung immer wieder in die Situation, irgendjemandem komplexe Zusammenhänge und Abläufe erklären zu müssen. Wo man früher auf einem Post-It oder einem Whiteboard ein paar Boxen und Pfeile gemalt hat, ist Post-Corona das digitale Medium König.

Wenn es doch nur auf der Kommandozeile ein Tool gäbe mit dem man … Ja, ich glaube nach sechzehn Kalendertürchen habt ihr bei diesen Artikeln vielleicht ein Muster erkannt.

dot

digraph G {
    A -> B;
    B -> C;
    C -> A;
}
dot -Tpng einfacher_graph.gv -o graph.png
Ein einfacher Graph mit dot.

Dot ist eine Graph-Beschreibungssprache und Teil des graphviz-Projektes. Das erste Release war „vor 1991“, aber DOT bringt einige Eigenschaften mit, die es heute noch relevant machen.

  • Graphen als Code. Einfach in Git einzuchecken und mit Änderungen zu tracken.
  • Einfache Syntax
  • Stabiles Interface. Da hat sich seit Jahrzehnten nichts daran geändert.
  • Graphen als Code. Ich sag es nochmaln Was das heißt, ist dass es leicht ist, den Output durch ein Programm zu erzeugen.
  • Mächtige Tool-Landschaft. Hauptsächlich ausgerichtet auf Leute, die viel mit Graphentheorie machen, aber nicht unnütz für den Softwareentwicklungs-Alltag.

Wissen kommunizieren

Der häufigste Fall in denen Entwickler künstlerisch tätig werden, ist wenn sie aufzeigen sollen, welche Systeme es gibt und wie sie miteinander interagieren. Meine Meinung zu diesem Thema: Je komplexer das Tool, das verwendet wurde, um diese Grafik zu erstellen, desto größer die Chance, dass das Wissen nachher obsolet ist.

digraph ECommerceArchitecture {
    frontend [label="Frontend", shape=box, style=filled, color=lightblue];
    authService [label="Authentication Service", shape=box, style=filled, color=lightgrey];
    productService [label="Product Service", shape=box, style=filled, color=lightgrey];
    orderService [label="Order Service", shape=box, style=filled, color=lightgrey];
    paymentService [label="Payment Service", shape=box, style=filled, color=lightgrey];
    notificationService [label="Notification Service", shape=box, style=filled, color=lightgrey];
    userDB [label="User Database", shape=cylinder, style=filled, color=gold];
    productDB [label="Product Database", shape=cylinder, style=filled, color=gold];
    orderDB [label="Order Database", shape=cylinder, style=filled, color=gold];
    externalShipping [label="External Shipping API", shape=parallelogram, style=filled, color=green];
    cache [label="Cache Layer", shape=ellipse, style=filled, color=orange];
    loadBalancer [label="Load Balancer", shape=trapezium, style=filled, color=red];
    messageQueue [label="Message Queue", shape=note, style=filled, color=pink];

    loadBalancer -> frontend;
    frontend -> productService [label="requests"];
    frontend -> orderService [label="sends orders"];
    frontend -> authService [label="authenticates"];
    authService -> userDB [label="queries"];
    productService -> productDB [label="queries"];
    productService -> cache [label="caches"];
    orderService -> orderDB [label="updates"];
    orderService -> paymentService [label="requests payment"];
    orderService -> externalShipping [label="arranges shipping"];
    orderService -> messageQueue [label="sends notifications"];
    paymentService -> userDB [label="verifies user"];
    notificationService -> messageQueue [label="receives"];
}
… es geht auch in komplexer!

In vielen Teams ist die Anpassung der Dokumentation Teil der Definition of Done. Du erstellst einen neuen Service? Trage ihn gleich mal hier ein. Besser noch: Wenn unsere Dokumentation aus Code entsteht, können wir diesen Code auch automatisch generieren. Wenn unser Service Mesh ohnehin in Code gegossen ist, können wir ihn auch grafisch darstellen.

Wissen gewinnen

Die einfache Syntax von dot macht es trivial, sie durch ein Skript zu generieren. Was eine hervorragende Möglichkeit sein kann, um sich einen Überblick oder Insights zu verschaffen.

#!/bin/bash

DIRECTORY="./node_modules/simple-update-notifier/"

escape_dot() {
    echo "$1" | sed -e 's/"/\\"/g' -e 's/-/\\-/g'
}

echo "digraph G {" > verzeichnis_baum.gv
echo "node [shape=plaintext]" >> verzeichnis_baum.gv

find "$DIRECTORY" | while read -r line; do
    parent_dir=$(dirname "$line")
    base_name=$(basename "$line")

    escaped_parent=$(escape_dot "$(basename "$parent_dir")")
    escaped_child=$(escape_dot "$base_name")

    if [ "$parent_dir" != "$line" ]; then
        echo "\"$escaped_parent\" -> \"$escaped_child\";" >> verzeichnis_baum.gv
    fi
done

# End the DOT graph
echo "}" >> verzeichnis_baum.gv

Anstelle von dot gibt es noch andere Render-Engines wie neato, circo und twopi. Wer schnell einen großen, baumartigen Graphen generieren möchte, greift am besten zu

sfdp -Tpng verzeichnis_baum.gv -o graph.png
Wie wäre es mit einem baumartigen Graphen? dafür eignet sich sfdp hervorragend.

Anstelle der besagten Rendereng Engines gibt auch Optionen in JavaScript, Python und einer Reihe anderer Programmiersprachen. Anstelle von Verzeichnisbäumen lassen sich auch Dependency-Graphen, Klassendiagramme, Organisationsstrukturen und alles andere, was man automatisch parsen kann, darstellen.

Mindmaps beliebiger Größe

Ich habe ja bereits David Allen zitiert: „Dein Gehirn ist, um Ideen zu haben, nicht sie zu lagern.“ Je mehr wir Ideen festhalten, desto besser kann unser Gehirn aufnehmen was da ist und Muster fortsetzen.

Nehmen wir eine klassische Retro (Beispiele hier sind fiktiv).

digraph retrospective {
    start [label="Start", shape=circle, style=filled, color=lightblue];
    stop [label="Stop", shape=circle, style=filled, color=lightblue];
    keep [label="Keep", shape=circle, style=filled, color=lightblue];

    bitte_puenktlich [label="Pünktlich zu Meetings erscheinen", shape=box, style=filled, color=yellow];
    zu_spaet_kommen [label="zu spät kommen", shape=box, style=filled, color=yellow];
    snacks [label="Gratis-Snacks in der Küche", shape=box, style=filled, color=yellow];
    technische_schulden [label="Technische Schulden sind außer Kontrolle", shape=box, style=filled, color=yellow];
    warteschleifenmusik [label="Warteschleifen-Musik in Google Meet einspielen", shape=box, style=filled, color=yellow];
    rails_update [label="Rails zwei Major Versionen hintenan", shape=box, style=filled, color=yellow];
    security_patches [label="hunderte ungepatchter Sicherheitslücken", shape=box, style=filled, color=yellow];
    performance_issues [label="Frontend laaaaaangsaaaaam", shape=box, style=filled, color=yellow];
    endlos_klassen [label="Klassen sind endlos lang", shape=box, style=filled, color=yellow];

    cluster_puenktlichkeit [label="Pünktlichkeit", shape=trapezium, style=filled, color=green];
    cluster_technische_schulden [label="Technische Schulden", shape=trapezium, style=filled, color=green];

    dot_voting_puenktlichkeit [label="5", shape=cylinder, style=filled];
    dot_voting_technische_schulden [label="23", shape=cylinder, style=filled];
    dot_voting_snacks [label="1", shape=cylinder, style=filled];
    dot_voting_musik [label="3", shape=cylinder, style=filled];

    action_item_puenktlichkeit_drohnen [label="Mechanische Wecker per Drohnen ausliefern", shape=box, style=filled, color=orange];
    action_item_mayflower_anheuern [label="Salesmenschen von Mayflower zurückrufen", shape=box, style=filled, color=orange];

    start -> bitte_puenktlich;
    start -> warteschleifenmusik;
    stop -> zu_spaet_kommen;
    stop -> technische_schulden;
    stop -> rails_update;
    stop -> security_patches;
    stop -> performance_issues;
    stop -> endlos_klassen;
    keep -> snacks;

    bitte_puenktlich -> cluster_puenktlichkeit;
    zu_spaet_kommen -> cluster_puenktlichkeit;
    technische_schulden -> cluster_technische_schulden;
    rails_update -> cluster_technische_schulden;
    security_patches -> cluster_technische_schulden;
    performance_issues -> cluster_technische_schulden;
    endlos_klassen -> cluster_technische_schulden;

    cluster_puenktlichkeit -> dot_voting_puenktlichkeit;
    snacks -> dot_voting_snacks;
    warteschleifenmusik -> dot_voting_musik;
    cluster_technische_schulden -> dot_voting_technische_schulden;

    cluster_puenktlichkeit -> action_item_puenktlichkeit_drohnen;
    cluster_technische_schulden -> action_item_mayflower_anheuern;
}

Um zu vermeiden, dass dieser Graph zu sehr in die Breite geht (dot-Graphen sind in der Regel sehr geordnet), können wir das GraphViz-Tool unflatten als Präprozessor darüber laufen lassen.

unflatten -f -l 3 graph.gv | dot -Tpng -o output.png

Ich mache öfter mal den Witz, dass wir anstelle von Miro einfach ein Git-Repo nehmen sollten, auf dem wir bei Ablauf des Timers unsere Post-Its committen. (Es ist so lange ein Witz bis wir es tatsächlich so machen …)

Für ein persönliches Brainstorming – um die eigenen Gedanken zu ordnen – taugt es auf jeden Fall.

Mit AI-Unterstützung

Das beste an Code-basierten Lösungen? Inhalte analoger Whiteboards kann man abfotografieren und von ChatGPT direkt in dot-Syntax übersetzen lassen.

Aus Foto mach dot – ChatGPT sei Dank.
Hi ChatGPT,
I have drawn this graph on paper. Could you convert this into DOT syntax for me?

ChatGPT’s Antwort:

It seems that the OCR did not successfully detect text from the image. Since the text is not extracted, I'll directly translate the visual representation into DOT syntax based on the image provided.

The image depicts a simple graph with three nodes labeled "Frontend", "Product Service", and "DB", with arrows indicating the direction of interaction. The arrow from "Frontend" to "Product Service" is labeled "get_products", and there is an unlabeled arrow from "Product Service" to "DB" with "SQL" written next to it.

Here's how this graph can be represented in DOT syntax:

dot
digraph G {
    Frontend -> ProductService [label="get_products"];
    ProductService -> DB [label="SQL"];
}

This syntax defines a directed graph where "Frontend" points to "ProductService" with a "get_products" label, and "ProductService" points to "DB" with a "SQL" label.

Der kompilierte Graph:

Der fertige Graph aus ChatGPT

DOT ist nicht das einzige Tool

… und bei weitem nicht das Hübscheste. Jedes moderne Data-Science-Framework bringt Visualisierungskomponenten mit. JavaScript-Tools wie Mermaid und D3.js machen komplexe und gleichzeitig ästhetische Visualisierungen zugänglich. Ansonsten gibt es Klassiker wie R Shiny und ggplot2, die Python-Bibliotheken Matplotlib, Seaborn, Plotly und Bokeh, sowie gnuplot und TikZ in LaTeX für harte eingestaubte Unix-Fans.

Unser Gehirn ist nicht text-basiert

Es könnte sich hier der Eindruck aufdrängen, dass ich ein Buchstabenfanatiker bin, der keine Bilder mag, dass ich am liebsten Computer hätte, die digitale Schreibmaschinen wären.

Stimmt nicht.

Text ist ein Artefakt der Moderne. Unsere Gehirne sind lange bevor es Sprache gab entstanden. Der Großteil unseres Gehirns agiert non-verbal.

Mein Punkt ist: Bilder (und Geräusche und haptisches Feedback) sind dann nützlich, wenn sie uns bei unserer Arbeit helfen. Wir sollten (und müssen) uns grafische Darstellung zunutze machen. Meine persönliche Präferenz ist es nur, vom grellen Kaleidoskop moderner Desktop-Umgebungen hinzugehen zu etwas, was ein wenig mehr Zen ist.

Shell-Weisheit des Tages
Pragmatismus

Als Entwickler sind wir sehr damit vertraut, dass Dinge nicht immer nach dem Lehrbuch verlaufen. Idealerweise sollte man Tests schreiben, technische Schulden unter Kontrolle halten, die Sicherheitslücken aus npm audit konstant auf 0 halten, Sprachen idiomatisch verwenden, sich bitte – nur einmal – an den Scrum Guide halten, nur um zu schauen, wie das ist. Idealismus vs. Pragmatismus schwingt in vielen täglichen Entscheidungen mit. Ein Produkt, das nicht rechtzeitig auf den Markt kommt, kann ein großer Haufen verbranntes Geld sein.

Als Kommandozeilen-Fan in der täglichen Arbeit ist es oft genau so.

Idealerweise benutze ich ausschließlich Kommandozeilen-Werkzeuge, um meine tägliche Arbeit zu tun. Ich komme überraschend weit damit, aber die letzten 10 Prozent würden disproportional aufwendig werden.

Zum schreiben meines Codes nutze ich vim, aber die ersten Wochen im Projekt benutze ich brav VSCode –bis ich wirklich verstanden habe, was in der Entwicklungsumgebung alles eingerichtet gehört.

Ich benutze einen Browser. Ich benutze das grafische Tool, von dem mir gesagt wurde, damit ginge es. Ich habe LibreOffice auf meinem Laptop installiert, nur für den Fall, dass ich schnell mal einen Papierbrief schreiben muss und LaTeX aus irgendwelchen Gründen wieder schwierig sein möchte.

Ich bin bereit, jedes meiner Werkzeuge für das Werkzeug zur Seite zu legen, mit dem die Arbeit schneller und besser geht – und lande so oft wieder auf der Kommandozeile.

Niemand möchte mit Hardlinern und Dogmatikern zusammenarbeiten. Die Kehrseite ist, dass man im Namen des „Pragmatismus“ die langfristige Effizienz aus den Augen verliert. Die „Postkorb-3“-Aufgaben – wie BWLer sie gerne nennen – „wichtig, aber nicht dringend“.

Die Balance liegt darin, in der täglichen Arbeit zu reflektieren. Sich vielleicht sogar harte Timer zu stellen, um nicht zu tief in „Rabbit Holes“ abzudriften.

Vielleicht erzähle ich hier niemanden etwas Neues. Es war mir wichtig klarzustellen, dass ich hier keinen extremen Pol vertreten möchte.

Avatar von Eric

Kommentare

2 Antworten zu „CLI-Adventskalender: dot“

  1. […] selbst-gemalte DOT-Diagramme (siehe meinen Adventskalender-Post zu diesem Thema) […]

  2. […] richtige Medium, um dieser Datei gerecht zu werden. Eine .vimrc ist das ultimative dotfile (siehe mein Artikel zu dotfiles), und sie von System zu System zu tragen ist eine gute […]

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.