1 Punkte von GN⁺ 2024-02-26 | 1 Kommentare | Auf WhatsApp teilen
  • Open-Source-Projekte mit etwa 10.000 bis 200.000 Zeilen Code können neben README und CONTRIBUTING ein ARCHITECTURE-Dokument bereitstellen, um neuen Mitwirkenden die Einarbeitung in die Codestruktur zu erleichtern
  • In unbekannten Projekten ist weniger das Problem, dass das Schreiben eines Patches ungefähr doppelt so lange dauert, sondern vielmehr, dass es zehnmal länger dauern kann, herauszufinden, wo etwas geändert werden muss
  • Das Dokument sollte die High-Level-Struktur und selten veränderliche Inhalte kurz festhalten; statt es ständig mit dem Code synchron zu halten, eignet sich eine Überprüfung einige Male pro Jahr
  • Die Kernbestandteile sind ein Überblick über das Problem und eine Codemap; sie sollte große Module und ihre Beziehungen zeigen und die Frage beantworten: „Wo ist der Code, der für X zuständig ist?“
  • Wichtige Namen, Architektur-Invarianten, Schichten- und Systemgrenzen sowie Querschnittsbelange sollten festgehalten werden; wenn man statt direkter Links zur Namenssuche anleitet, sinkt der Wartungsaufwand

Welche Kosten ein ARCHITECTURE-Dokument reduziert

  • Der größte Unterschied zwischen gelegentlichen Beitragenden und Core-Entwicklern in einem Open-Source-Projekt ist, ob sie die physische Architektur des Projekts kennen
  • In einer unbekannten Codebasis liest man Dateien nacheinander wie logisch zusammengehörige Fragmente in beliebiger Reihenfolge
  • Entwickler, die bereits bedeutende Beiträge geleistet haben, haben eine Codekarte im Kopf, springen direkt an die benötigte Stelle und können den betreffenden Code bei Bedarf auch verschieben
  • Eine ARCHITECTURE-Datei ist ein kostengünstiges Mittel, um diese Lücke zu verkleinern
  • Das Dokument sollte kurz sein
    • Weil alle, die wiederholt beitragen, es lesen sollten
    • Je kürzer es ist, desto geringer ist die Wahrscheinlichkeit, dass es durch zukünftige Änderungen ungültig wird
  • Als Maßstab gilt, dass ARCHITECTURE Inhalte enthalten sollte, die sich nicht häufig ändern
    • Man versucht nicht, es ständig mit dem Code synchron zu halten
    • Stattdessen überprüft man es einige Male pro Jahr erneut

Was sollte enthalten sein?

  • Zunächst wird das Problem, das das Projekt löst, auf Überblicksebene zusammengefasst
  • Anschließend wird eine einigermaßen detaillierte Codemap erstellt
    • Sie beschreibt Module auf großer Ebene und ihre Beziehungen zueinander
    • Sie sollte beantworten: „Wo befindet sich das, was X tut?“
    • Sie sollte auch beantworten: „Was macht das hier, das ich gerade betrachte?“
  • Auf die internen Abläufe der einzelnen Module geht sie nicht tief ein
    • Solche Inhalte gehören in separate Dokumente oder, noch besser, in Inline-Dokumentation
    • Eine Codemap ist eine Landkarte, kein Atlas mit Karten einzelner Bundesländer
  • Beim Schreiben der Codemap kann man zugleich die Projektstruktur überprüfen
    • Man kann prüfen, ob Dinge, die in der Codemap nahe beieinander liegen sollen, auch in der Ausgabe von tree . benachbart sind
  • Wichtige Dateien, Module und Typnamen werden explizit genannt
    • Direkte Links sollten vermieden werden, weil sie mit der Zeit brechen können
    • Stattdessen führt man zur Symbolsuche per Name; so lassen sich ohne Wartungsaufwand auch verwandte Einträge mit ähnlichen Namen finden
  • Architektur-Invarianten sollten explizit notiert werden
    • Wichtige Invarianten treten häufig in der Form auf, dass etwas „nicht vorhanden“ ist
    • In der Webentwicklung kann es zum Beispiel schwierig sein, allein durch Lesen des Codes zu erkennen, dass die Model-Schicht nicht von der View abhängt
  • Auch Grenzen zwischen Schichten und Systemen sollten markiert werden
    • Grenzen deuten Informationen über die Implementierung des dahinterliegenden Systems an
    • Sie schränken alle möglichen Implementierungen ein
    • Gute Grenzen sind im Code schwer zufällig zu entdecken, daher ist ihre Dokumentation nützlich
  • Nach der Codemap wird ein eigener Abschnitt für Querschnittsbelange hinzugefügt
  • Ein Beispiel als Referenz findet sich in der architecture.md von rust-analyzer

1 Kommentare

 
GN⁺ 2024-02-26
Meinungen auf Hacker News
  • Ich finde die Idee gut, und unabhängig von der Größe des Repositorys hat eine Architekturbeschreibung meiner Meinung nach auch im README ihren Platz.
    Zum Beispiel hielt ich es für wichtig, dass alle Leser den Arbeitsablauf sehen und verstehen können, deshalb habe ich bewusst ein Mermaid-Sequenzdiagramm[1] ins Haupt-README aufgenommen[2].
    [1] https://mermaid.js.org/syntax/sequenceDiagram.html
    [2] https://github.com/hbcondo/revenut-app?tab=readme-ov-file#-w...

    • Ein Tool, das Mermaid-Diagramme aus natürlicher Sprache erzeugt, wäre ziemlich cool. Wäre eine Überlegung wert.
  • Klingt nach wirklich gutem Rat.
    Ich wünschte, Tools zur Visualisierung der Architektur laufender Systeme wären besser. Es ist seltsam, dass Code zu lesen oder Markdown-Dateien anzusehen immer noch der aktuelle Stand ist. Mit Glück gibt es vielleicht ein Mermaid-Diagramm.
    Ich fände es gut, wenn sich die Architektur in Echtzeit von selbst offenbaren würde. Eine Art Observability auf Makroebene sollte standardmäßig eingebaut sein; das würde allen helfen, Computing besser zu verstehen, und auch der Menschheit dabei, sich selbst zu augmentieren.

    • Visualisierungen wie dep-tree ließen sich gut um Keyword-Suche oder LLM-Vektorsuche ergänzen. Bei einer Anfrage würden relevante Dateien und Cluster hervorgehoben.
  • Für Open-Source-Projekte mit vielen gelegentlichen Beitragenden sieht das nach einem wartungsarmen Modell aus. Bei Projekten mit dedizierten Engineers wären auch ADRs eine Überlegung wert.
    ADRs brauchen mehr Pflege, halten aber fest, „warum es so gemacht wurde“ und „welche Alternativen geprüft wurden“, was bei einem Redesign sehr nützlich ist.
    Siehe: https://adr.github.io/

    • Hier scheint mir „zusammen“ passender als „stattdessen“.
      ARCHITECTURE.md beschreibt den aktuellen Architekturzustand, und ADRs sind die Aufzeichnung der Entscheidungen, die dorthin geführt haben. Beides ist sehr nützlich.
    • Auch in unserer Firma gibt es nutzlose Dokumente, die Architekten schreiben, und die meisten sind genau so.
      Microservices, Kafka, Kubernetes: weil wir aktuell 4.000 Nutzer haben, aber was, wenn es irgendwann 1 Milliarde werden?
      GraphDB: weil SQL vielleicht nicht ausreicht.
      ElasticSearch: weil wir vielleicht neben Statistiken auch Volltextsuche brauchen.
      Aber die meisten dieser Dokumente sind am Ende nur eine Kurzform von: „Ich will eine neue Architektur/Technologie ausprobieren, weil sie interessant ist; ein Kollege bei FAANG nutzt sie; ich habe das Buch gelesen; es sieht gut im Lebenslauf aus.“
      Wenn sie dann zum Entwurf des nächsten großen Projekts weiterziehen, muss unser Team mehr Services als Teammitglieder sowie die oben genannten Datenbanken und Technologien weiter synchron halten. Natürlich wird so getan, als seien solche Probleme viel simpler, als „große Architekturentscheidungen“ zu treffen.
  • Mir kam gerade der Gedanke: Jede IDE, die ich je benutzt habe, zeigt links die Ordnerstruktur des Projekts als normalen Verzeichnisbaum. Gibt es eine IDE, mit der man ein Projekt als Dependency-Graph durchsuchen kann?

    • Keine direkte Antwort auf die Frage, aber letztlich scheint es darum zu gehen, die Dateistruktur besser visualisieren zu wollen.
      Eine Darstellung als Inhaltsverzeichnis passt meiner Meinung nach nicht gut. In meinem heutigen Coding-Workflow öffne ich ein Terminal, starte darin ranger und wechsle beim Navigieren durch linke und rechte Verzeichnisstrukturen per Tab zu diesem Terminal. Ich öffne VSCode und lasse im Split-Terminal oben ein normales Terminal und unten Ranger laufen. Midnight Commander geht auch; eigentlich reicht jeder TUI-Dateimanager.
      Außerdem habe ich begonnen, in die architecture.md des Projekts eine Code-Karte einzubauen. Mit tree -L bekommt man ein für Markdown gut geeignetes Dateistruktur-Baumdiagramm in der gewünschten Tiefe. Diese Ausgabe füge ich in Markdown ein und ergänze hinter jeder Datei/jedem Ordner einen Kommentar mit weniger als 10 Wörtern, der den Zweck erklärt.
      Ranger - https://github.com/ranger/ranger
      Midnight Commander - https://midnight-commander.org/
    • Genau denselben Gedanken hatte ich auch.
      Ich habe zwei Ideen, wie das aussehen könnte.
      Erstens: mehrere Verzeichnisbäume, die Dateien mithilfe symbolischer Links orthogonal organisieren. Die übliche Verzeichnisstruktur ist in Client/Server aufgeteilt, aber was, wenn man sie nach Features aufteilen möchte? Eine IDE könnte das viel einfacher ermöglichen.
      Zweitens: In der Richtung dieses Artikels würde ich mir wünschen, dass die IDE Bookmarks anlegt und es leichter macht, zwischen ihnen zu wechseln und anderen den Code zu erklären. Manchmal möchte ich Kommentare hinterlassen und per Klick an eine andere Stelle der Codebase springen. Wenn man solche Dinge verbindet, kann man eine Erzählung aufbauen, die über die gesamte Codebase hinweg erklärt, wie sie funktioniert.
      Ich frage mich, ob jemand an so etwas arbeitet.
    • Wie würde das in der Praxis aussehen? Wie könnte man zum Beispiel zyklische Abhängigkeiten handhaben?
    • Vielleicht ist es eigentlich ein Multitree, den du willst.
  • Ich denke, man sollte vorsichtig sein, das, was der Autor hier sagt, zu stark auf allgemeine Softwareprojekte auszuweiten.
    In großen Open-Source-Projekten mit vielen Beitragenden, denen Kontext fehlt, lohnt es sich sehr, solche Dokumente zu pflegen. Aber bei kleinen Arbeitsprojekten habe ich gesehen, dass von Entwicklern eingecheckte Dokumente am Ende alle ungepflegt bleiben.

    • Ich habe mit Teams ein paar Architektur-Sessions gemacht, und sie waren immer wertvoll.
      Zumindest stellt man fest, dass Teammitglieder sehr unterschiedliche Vorstellungen von der aktuellen und der idealen Architektur haben. Allein das explizit sichtbar zu machen, ist es wert, ein Dokument zu erstellen.
      Und „Dokumente werden nicht gepflegt“ ist ein sehr schwacher Grund, keine Dokumente zu erstellen. Denn jedes Dokument, selbst ein veraltetes oder subtil falsches, ist besser als „keine Dokumentation“.
  • Vor ein paar Jahren habe ich bei einem meiner größeren Nebenprojekte einen ähnlichen Ansatz ausprobiert
    https://github.com/shipmight/shipmight/blob/master/src/ARCHI...
    Am Anfang jeder Datei gab es einen Link-Baum zu den anderen ARCHITECTURE.md-Dateien im Repository. Zum Beispiel so: ARCHITECTURE.md <- aktueller Standort, backend/ARCHITECTURE.md, backend/api/ARCHITECTURE.md, backend/cli/ARCHITECTURE.md, backend/ui/ARCHITECTURE.md, backend/utils/ARCHITECTURE.md, frontend/ARCHITECTURE.md, internal-charts/ARCHITECTURE.md

  • Je kürzer, desto geringer die Wahrscheinlichkeit, dass künftige Änderungen sie ungültig machen. Die zentrale Faustregel für ARCHITECTURE ist, nur Inhalte aufzuschreiben, die sich nicht häufig ändern. Man sollte nicht versuchen, sie mit dem Code synchron zu halten
    Interfaces ändern sich mit geringerer Wahrscheinlichkeit und sind auch schwieriger zu ändern. Das ist Parnas’ Sicht auf die Kriterien, nach denen man ein System in Module zerlegt
    Ich stimme zu, dass es schwierig ist, eine Codebase zu verstehen. Namen für „Patterns“ zu vergeben hilft bis zu einem gewissen Grad, aber am Ende muss man doch ziemlich viel lesen
    Auf GitHub fühlen sich Commit-Messages pro Datei oft wie Erklärungen an. Könnte das vielleicht nützlicher sein?

  • In jedem Projekt, an dem ich beteiligt war, bekam man beim Onboarding Architekturdiagramme und eine kurze Erklärung der Komponenten
    Deshalb überrascht es mich, dass das in Open Source nicht so üblich ist

    • Die „Beschreibung der Komponenten“ ist genau das Problem. Jemand muss sie nämlich liefern
      In Open-Source-Projekten gibt es keinen ersten Arbeitstag eines Mitarbeiters, also auch keine solche Einführung
      Wenn man nicht sehr viel Zeit hat, sind solche Erklärungen nicht besonders gut. Von einem Mitarbeiter erwartet man, dass er ein paar Wochen braucht, bis er allein etwas hinbekommt; wir als Security Consultants hören dagegen alle zwei Wochen eine komplett neue Erklärung. Das Problem ist, dass diese Erklärungen improvisiert und unstrukturiert sind und die sprechende Person wegen des Fluchs des Wissens viele irrelevante Details erzählt
      Wahrscheinlich wäre es am besten, wenn jemand, der neu ins Repository kommt, das einmal schreibt und es danach nur noch gepflegt wird. Die zweitbeste Lösung wäre, dass irgendjemand – statt jedes Mal spontan zu erklären – etwa eine Minute darüber nachdenkt, was hinein- und was herausgehört, und es dann aufschreibt. Wie der Autor sagte, sollte diese Datei die High-Level-Architektur des Projekts beschreiben und kurz sein. Wiederkehrende Contributor sollten sie alle lesen, und je kürzer sie ist, desto geringer ist auch die Wahrscheinlichkeit, dass sie durch künftige Änderungen ungültig wird
  • Ich habe das immer als sehr nützliche Praxis empfunden. Viele Projekte haben ein paar Kerndateien, in denen die meisten Änderungen stattfinden, oder entsprechende Packages/Module usw.
    Wenn neue Contributor oder Contributor, die nach längerer Zeit zurückkehren, sich diese schnell erschließen können, verkürzt das die Anlaufzeit im Projekt erheblich
    Ich habe in mehreren Jobs Architekturdateien zu Projekten hinzugefügt [0], [1], und die Reaktionen waren positiv. Nicht perfekt, aber besser als nichts
    [0]: https://github.com/zapier/zapier-platform/pull/324
    [1]: https://github.com/stripe/stripe-cli/blob/master/ARCHITECTUR...

    • Gibt es auf GitHub eine Möglichkeit, so etwas automatisch zu sehen? Zum Beispiel eine Art Heatmap der Dateiänderungen
  • Früher mochte ich solche kleinen Docs/Diagramme-as-Code-Standards sehr
    README-getriebene Entwicklung, ARCHITECTURE.md, ADR, arc42, C4 usw.
    Heute lege ich einfach einen Obsidian-Vault im Ordner /docs des git-Repositorys ab
    Statt die Standards anderer Leute zu verwenden, organisiere und refaktoriere ich die Dokumentation laufend, so wie ich in Obsidian persönliche Notizen pflege
    Anfangs wollte ich eine gemeinsame Markdown-Teilmenge verwenden, die sowohl mit GitHubs GFM als auch mit Obsidian funktioniert, habe das aber aufgegeben; inzwischen nutze ich Obsidian-Markdown unverändert, einschließlich proprietärer Features wie Dataview-Plugin und Templates
    Mermaid und LaTeX sind in Obsidian integriert, und es gibt auch ein PlantUML-Plugin. Für visuelle Zeichnungen/Diagramme verwende ich das eingebaute Canvas, DrawIO und Excalidraw