1 Punkte von GN⁺ 2025-09-09 | 4 Kommentare | Auf WhatsApp teilen
  • In früheren Ada-Entwicklungsumgebungen wurde das Problem der Code-Formatierung bereits gelöst
  • Entwickler arbeiteten mit Code in Form der DIANA-Zwischendarstellung (IR) und betrachteten ihn mit jeweils eigenen Pretty-Printing-Einstellungen
  • Auch heute gibt es durch Linter oder Formatierungsrichtlinien immer wieder Ineffizienz und Diskussionen
  • Die damalige Rational-R1000-Workstation bot eine innovative Entwicklungsumgebung und entsprechende Funktionen
  • Mit Blick auf die Code-Formatierung schlägt der Beitrag vor, sich an Ansätzen einer früheren Generation zu orientieren, um heutige Entwicklungspraktiken zu verändern

Die Debatte um Code-Formatierung – eine Lösung aus den 1980er-Jahren

  • Der Autor erwähnt seine Erfahrungen mit Mr. Paige, einem Informatiklehrer, der während seiner Highschool-Zeit an einem Ada-Compiler gearbeitet hatte
  • Als er sich 2016 über die umständliche Einrichtung eines Linter-Tools beschwerte und fragte, „warum wir uns mit so etwas immer noch herumschlagen müssen“, erfuhr er, dass dieses Problem bereits vor über 40 Jahren gelöst worden war

Das Aufkommen von Ada und DIANA

  • Ada-Entwickler speicherten nicht einfach textuellen Quellcode, sondern nutzten eine Zwischendarstellung namens DIANA (Descriptive Intermediate Attributed Notation for Ada)
  • Jeder Entwickler konnte den Quelltext mit seinen eigenen Pretty-Printing-Einstellungen in der gewünschten Form anzeigen
  • Es gab weder Formatierungsdebatten noch Linter-Probleme, und im Editor ließ sich der Programmbaum direkt bearbeiten, ähnlich wie beim heutigen projectional editing

Rational R1000 – eine wegweisende Entwicklungsumgebung

  • Die Rational R1000-Workstation integrierte zahlreiche fortschrittliche Funktionen wie inkrementelle Kompilierung, statische Analyse, Versionsverwaltung und Debugging
  • Sie wurde für wichtige Softwareprojekte etwa beim DoD, der Internationalen Raumstation (ISS) und dem Kampfflugzeug F-22 eingesetzt und trug auch zur Entstehung von UML bei
  • Laut Grady Booch war das R1000 eine auf DIANA basierende Maschine, die keinen Quellcode speicherte, sondern ausschließlich Pretty-Printing des DIANA-Baums nutzte

Vorteile der DIANA-basierten Entwicklung

  • Es gab keinen Bedarf an Formatierungsdebatten, Linter-Setups oder einer Vereinheitlichung der Editor-Umgebung
  • Hardwarebeschleunigung ermöglichte inkrementelle Kompilierung, einfaches Refactoring, schnelle Integration und insgesamt eine innovative Entwicklungserfahrung
  • Das hatte großen Einfluss auf die Entwicklungseffizienz und die Arbeit an großen Systemen

Was das für heute bedeutet

  • Hardwarebeschleunigte Kompilierung ist heute weniger wichtig, doch das Problem der Code-Formatierung ist weiterhin nur unzureichend gelöst
  • Auch wenn projectional editing oder Live-Umgebungen nicht zum Mainstream gehören, ist es an der Zeit, wie bei den früheren Ansätzen über die Einführung effizienterer und weniger umstrittener Entwicklungspraktiken nachzudenken

Referenzmaterial

  • Der Autor zitiert bei seiner Untersuchung dieses Themas verschiedene Dokumente und technische Berichte zum R1000

4 Kommentare

 
ndrgrd 2025-09-10

Soweit ich weiß, gibt es für gemeinsam genutzten Code bereits die Funktion, ihn mit einheitlichen Einstellungen automatisch zu formatieren, und ich denke, dass Unternehmen das häufig nutzen.

 
euphcat 2025-09-10

Ich denke, der Punkt ist nicht automatisches Formatieren, sondern dass schon die Annahme, ein bestimmtes Format sei überlegen, oder der Prozess, das eigene Format aufzugeben und sich an ein ungewohntes anzupassen, unnötig ist. Die Logik ist also, eine Zwischenrepräsentation zu speichern, die nicht an Formatierung gebunden ist, und sie dann je nach Nutzer in der jeweils bequemsten Form hübsch auszugeben.

 
ndrgrd 2025-09-10

Ich wollte damit sagen, dass man mit automatischer Formatierung in den bestehenden Sprachen dasselbe erreichen kann, auch ohne Zwischenrepräsentation, aber meine Erklärung war wohl unzureichend.

 
GN⁺ 2025-09-09
Hacker-News-Kommentare
  • Ich verstehe nicht, warum Leute so viel Wert auf Linter-Einstellungen legen; das ist offensichtlich eine nutzlose Debatte. Man sollte sich einfach auf eine Variante festlegen, den Linter automatisch laufen lassen und fertig. Es ist wichtiger, Zeit für echte Softwareentwicklung zu haben. Egal welches Format man im Team beschließt: Nach einer Woche hat man sich daran gewöhnt.
    • Es wird darauf hingewiesen, dass Source-Code-Formatter und Lint-Programme nicht dasselbe sind: Ein Formatter kümmert sich nur um das Layout des Codes, während ein Linter mögliche Bugs oder Fehler im Code findet. Manche Tools unterstützen beides, aber das ist ein Implementierungsdetail. Was „lint“ ist, kann man hier nachlesen: https://en.wikipedia.org/wiki/Lint_(software)
    • Ich verbringe die meiste Zeit damit, Code zu „lesen“, und das Layout des Codes beeinflusst, wie schnell ich ihn lesen kann. Man kann sich zwar an unterschiedliche Layouts gewöhnen, aber nicht jedes ist gleich leicht lesbar. Ich merke mir Code über visuelle Muster und lese ihn in Blöcken anhand des Layouts. Paradoxerweise habe ich Aphantasie und kann Dinge nicht mit dem inneren Auge visualisieren, erinnere mich aber trotzdem besser über visuelle Hinweise.
    • Manche Linter-Einstellungen haben eindeutig Vorteile. Wenn man zum Beispiel in Tabellen ein trailing comma verwendet, muss man beim Hinzufügen eines neuen Eintrags in der letzten Zeile nur eine Zeile ändern, und auch der diff wird einfacher. Eine schlechte Wahl macht mir also das Leben schwerer. Dasselbe gilt für sortierte Listen oder Includes: Wenn nicht sortiert wird, hängt man neue Einträge immer ans Ende, was viele Merge-Konflikte verursacht. So wie automatische Formatter Zeit sparen, sollte auch Sortierung Zeit sparen. Und ich bin empfindlich gegenüber inkonsistenten Stilen. Am wichtigsten ist, sich auf genau einen Stil zu einigen.
    • Um die Detailoptionen kümmere ich mich nicht so sehr, aber ich halte gemeinsame Linter-Einstellungen für essenziell, um unnötiges Rauschen bei PRs zu reduzieren. Dass git und verschiedene PLs nur zeilenbasiert arbeiten, wirkt auf mich nicht elegant. In 20 Jahren Karriere habe ich nur einmal ein raffinierteres Vorgehen gesehen, etwa in der Sprache Ada. Etwas wirklich Elegantes und Effizientes zu bauen ist schwer, und wenn es bereits ausreichend gute Alternativen gibt, verbreitet es sich noch schwerer.
    • Ich bin als Jüngerer auch einmal in diese Debatte hineingeraten. Der Grund war, dass ich irrtümlich dachte, ich sei der Klügste im Team. Ich glaubte, meine Meinung sei am wichtigsten. Ich war überzeugt, alle müssten auf mich hören. Aber ich lag falsch.
  • Der Trade-off hier ist, dass bei anderen Formaten als Text die Nutzbarkeit allgemeiner Tools wie grep, diff, sed oder Versionsverwaltung sinkt. Am Ende steigt dadurch die Abhängigkeit von speziellen Tools, Formaten oder IDE-Erweiterungen. Die Stärke der Unix-Philosophie liegt in der Komponierbarkeit über Plain Text. Es gibt eine einfache Frage, mit der sich diese Debatte gut zuspitzen lässt: Wenn man im Editor nur die Breite der Einrückung frei einstellen könnte, gäbe es dann noch weitere Argumente der Tab-Befürworter?
    • Der textbasierte Ansatz hat Vorteile, aber ich habe das Gefühl, wir hätten nur ein Stück absteigen und dann einen höheren Berg besteigen können, nämlich Projectional Editing, stattdessen irren wir unten herum. Bei Code mit strukturellen Informationen funktionieren alle diese Beispiele besser: Für die Symbolsuche, die ich viel häufiger benutze als Text-grep, kann man etwa ast-grep verwenden; diff kann wie bei semanticdiff.com strukturelle Verschiebungen unterstützen oder bedeutungslose Änderungen ignorieren. Als Alternative zu sed kann man @codemod/cli nutzen. Auch bei Versionsverwaltung wurde viel experimentiert, etwa in Sprachen wie Unison, um Konflikte durch nicht-semantische Änderungen wie Reihenfolge oder Whitespace automatisch zu vermeiden.
    • Diese Idee taucht immer wieder auf, aber statt einfach einmal einen Formatter laufen zu lassen, braucht man plötzlich extrem komplexe Tools, und der Nutzen steht nicht im Verhältnis zu den Kosten. Dass jeder Entwickler alles nach seinem eigenen Geschmack sehen kann, bringt in der Praxis nicht viel. In allen Teams, mit denen ich bisher gearbeitet habe, wurden gemeinsam Regeln festgelegt und per Formatter erzwungen; anfangs war man vielleicht nicht einverstanden, aber schnell daran gewöhnt. Debatten über Formatting sind ein Paradebeispiel für Zeitverschwendung.
    • grep, diff, sed und zeilenbasierte Merges sind für Code-Manipulation eigentlich schlechte Tools. Statt diese Debatte zu führen, sollte man lieber über bessere Werkzeuge nachdenken.
    • Wenn man eine Intermediate Representation als Text hält, funktionieren grep/diff/sed alle weiterhin. Wenn man nur AST-basierte Formatter verwendet, könnte der Code in einer auf einen bestimmten AST normalisierten Form gespeichert werden; der Editor parst den AST, zeigt ihn dem Benutzer im gewünschten Format an und wandelt beim Speichern wieder in die normalisierte Form zurück.
    • Das gesamte Betriebssystem wurde auf Grundlage solcher Source-Dateien gebaut. Auch die Unix-Philosophie kommt erst dann wirklich zur Geltung, wenn alle Tools sich auf Plain-Text konzentrieren und ihn parsen können.
  • Ich denke, dass Source-Code-Formatting klar auch typografische Elemente hat. Ich stimme nicht der Behauptung zu, das sei rein persönliche Vorliebe. Bestimmtes Formatting ist ein Mittel, Bedeutung und Struktur wirksam zu vermitteln. Wenn man mit automatisierten Tools nur minimale Tokens serialisiert und später wiederherstellt, geht dieser Wert verloren. https://naildrivin5.com/blog/2013/05/17/source-code-typograp...
    • Fachleute aus dem Druckbereich haben sich lange mit großem Aufwand um Abstände und Ausrichtung in Tabellen oder Formeln gekümmert. Außenstehenden fällt das oft nicht auf, aber es war sehr wichtig. Ich glaube, dass auch bei Source Code Fortschritte in Richtung ausgefeilterer Formatierung möglich sind.
    • Zum Beispiel gibt es Beschwerden darüber, dass der Python-Formatter black SQLAlchemy-Queries in zu viele Zeilen aufteilt und dadurch die Lesbarkeit eher verschlechtert.
    • Ich habe mich immer gefragt, warum so viele Leute die Bedeutung von Typografie im Code nicht wahrnehmen.
    • Sich um Typografie zu kümmern und gleichzeitig unkritisch Programmiersprachenkonventionen zu folgen, scheint mir die falsche Richtung zu sein. Es gibt zum Beispiel eine Kultur, in der Wörter wie register bereitwillig verwendet werden, während Pointer mit einem Sternchen (*) notiert werden. Dabei könnte jede einzelne Notation intuitiver und klarer sein, trotzdem hält man an komplizierten und schwer lesbaren Formen fest. Auch Symbole oder reservierte Wörter könnte man durch vertrautere und natürlichere Begriffe ersetzen, aber man klammert sich zu sehr an Traditionen und bestehende Konventionen und opfert dafür die Lesbarkeit. Als Beispiel wird erklärt, dass sich die strcpy-Funktion in C mit klareren, besser lesbaren Begriffen und Syntax vollständig neu gestalten ließe.
    • Es wird erklärt, dass Parameterdeklarationen in C aus Modifiers, Datentyp und Namen bestehen, und mit Beispielen wie char *argv[] wird die Lesbarkeitsproblematik komplexer Deklarationen kritisiert. Auch C++-Stile beim Formatting, etwa char* a, b, können Missverständnisse erzeugen; solche Stile sollte man deshalb vermeiden.
  • Ich stimme der Prämisse dieser Debatte nicht zu. Code-Formatting ist ein sehr wichtiges Kommunikationsmittel. Gutes Formatting signalisiert, dass ein Entwickler (1) die Bedeutung von Formatting erkennt, (2) Regeln gut einhält, (3) guten Geschmack hat und (4) in Ausnahmesituationen über ein gutes Urteilsvermögen verfügt. Diese vier Punkte sind wichtige Fähigkeiten, die weit über reines Formatting hinausgehen und die generelle Entwicklerkompetenz betreffen. Auto-Formatter oder Linter-Regeln schwächen dieses Signal jedoch ab und lassen nach Goodharts Gesetz den ursprünglichen Zweck verloren gehen.
    • Es wird empfohlen, den Blogbeitrag direkt zu lesen, weil er kurz und einfach ist. Man solle nicht allein beim Titel sofort abwehrend reagieren, sondern den Kontext der Wörter „should“ und „unnecessary“ verstehen.
    • Wer sich nicht für Formatting interessiert, hat meiner Meinung nach entweder (1) nie erlebt, dass mehrere Personen dieselbe Datei bearbeiten, (2) nie Branches gemergt, (3) nie eine große Codebasis gewartet, (4) nie große Refactorings durchgeführt, (5) nie Code-Historie untersucht oder diff-/Vergleichstools genutzt, (6) nie Automatisierungswerkzeuge für Codebasen entwickelt oder (7) arbeitet ohne Bewusstsein für Zusammenarbeit und kümmert sich nur um die eigenen Vorlieben.
    • Wenn all diese Punkte mit „nein“ beantwortet werden, dann reicht es meiner Meinung nach völlig, das Formatting einfach beim Pass/Commit zu automatisieren und CI fehlschlagen zu lassen, wenn die Automatisierung nicht durchlaufen wurde. Statt sich an Details festzubeißen, ist es eher ein Vorteil, sich einfach an den Standard zu halten und den eigenen Stil aufzugeben. Wenn man die Defaults beibehält, wirkt der Code für alle, die ihn ansehen, vertraut. Außerdem sind Formatting und Linting zwar verschieden, lassen sich aber beide mit Automatisierungstools auf einmal lösen.
    • Dasselbe Urteil könne man auch aus Handschrift ableiten; scherzhaft wird ergänzt, man sollte PRs künftig in Schreibschrift einreichen lassen.
    • Sich auf den „Geschmack bei der Auswahl guter Formatting-Regeln“ zu verlassen, führt eher zu Debatten und Zeitverschwendung. Besser ist es, wie bei Go oder Rust den eingebauten Formattern zu vertrauen.
  • Versuche, Code auf Basis von Syntaxbäumen zu speichern und den für Menschen sichtbaren Code daraus zu rendern, gibt es schon seit 20 bis 25 Jahren. Diese Entwicklung geht auf die 90er zurück, als Refactoring erstmals populär wurde. IDEs wie Visual Age führten ein Modell ein, bei dem Code nicht im Dateisystem, sondern in einer Datenbank gespeichert wurde. Auch Intentional Programming oder modellbasierte Entwicklung gehören zu diesem Zyklus. Das Wesen von Refactoring ist AST-Transformation; Symbolnamen umzubenennen ist dort sehr einfach, ohne dass man direkt im Source Code suchen und ersetzen muss. Trotzdem sind Menschen weiterhin an Dateibearbeitung gewöhnt, und es gibt Widerstand und Reibung dagegen, direkt die Struktur selbst zu speichern. Dass wir nach all der Zeit immer noch Formatting-Debatten führen, zeigt gerade den Bedarf an solchen Alternativen. Es ist häufig, dass nicht einmal robustes Symbol Rename auf Sprach- oder Editor-Ebene ordentlich angeboten wird.
    • Dazu die Gegenmeinung, dass hier Abstraktionsebenen vermischt werden. Auch ein AST muss letztlich in einer Datei gespeichert werden, daher unterscheidet sich das nicht wesentlich davon, auf menschenlesbaren Dateien AST-aware-Tools laufen zu lassen. Das Speicherformat sei nicht so wichtig; im Kern gehe es um klügere Tools. Als Beispiele werden Microsofts Roslyn oder die Richtung moderner Compiler genannt, über APIs mit Codebasen zu interagieren.
  • Es wird direkt ein Beispiel dafür gegeben, dass sich manches Formatting nicht allein aus dem AST ableiten lässt. Wenn es zum Beispiel mehrere Assignment-Zeilen gibt, kann man sie in drei Zeilen bündig ausrichten, am = ausrichten oder durch zusätzliche Einrückung die strukturelle Tiefe stärker sichtbar machen. Wenn man die Werte selbst hervorheben will, richtet man Zahlen rechtsbündig aus; wenn man Struktur betonen will, richtet man Member-Variablen übersichtlich aneinander aus. Welcher Aspekt des Codes hervorgehoben werden soll, kann je nach Autor verschieden sein. Ohne zusätzliche Metadaten lasse sich diese Information nicht aus dem AST extrahieren.
    • Ich verstehe den Punkt, aber in der Praxis benutze ich eigentlich nur die ersten beiden Varianten. Das eigentliche Ziel war eher Lesbarkeit als Hervorhebung. Beim Umwandeln in einen AST geht zwar etwas verloren, aber in diesem Fall ist der Gewinn viel größer. Außerdem wären Variationen zur Hervorhebung, die im AST erhalten bleiben, durchaus möglich, etwa setValue([bar, glob], 1) oder eine Kommentar-Syntax für Style-Overrides.
    • „Wünschenswertes Code-Formatting“ ist letztlich subjektiv; wie im Beispiel bevorzugen manche 2/4/8 Leerzeichen, andere die Ausrichtung an Spalten. Ein AST enthält keine Formatting-Informationen des Source Codes und kann sie daher nicht automatisch ableiten.
    • Das zweite und dritte Formatting-Beispiel sind in Wirklichkeit strukturelle Designprobleme, also Verstöße gegen das Law of Demeter, und gehören nicht in die Kategorie Formatting.
  • Projectional Editing kann auch auf Textquellen angewendet werden. Es gibt ein Demo-Video aus JetBrains MPS, das zeigt, wie Tabellen direkt aus Code gerendert werden: https://www.youtube.com/watch?v=XolJx4GfMmg&t=63s Es wird der Wunsch geäußert, dass eine IDE Dictionaries als Tabellen rendern kann. Schon heute existieren teilweise ähnliche Funktionen wie Code Folding, Inlay Hints oder HTML-gerenderte Docstrings. https://x.com/efortis/status/1922427544470438381
  • Es wird gesagt, dass wir derzeit die Grenze haben, etwas Abstrakteres als Plain Text nicht sofort akzeptieren zu können. Selbst wenn man es versucht, wird am Ende doch wieder auf eine Plain-Text-Projektion heruntergebrochen. Von Morse Code bis Unicode habe sich eine „gewaltige Lookup-Tabelle (GLUT)“ angesammelt, die unsere heutige Kultur des Symbolentzifferns hervorgebracht habe. Hebt man das Abstraktionsniveau an, entstehen für Anwendungen passendere Symbolmengen, aber die dazugehörigen Tools erscheinen nicht. Am Ende wird doch wieder alles in Textübertragung umgewandelt und geparst, etwa bei CSV oder Markdown. Auch für XML gibt es spezielle Editoren, aber am Ende wollen die Leute doch in Plain Text editieren. Wegen Problemen mit Zeichenkodierung oder Sonderzeichen ist das aber nicht uneingeschränkt positiv.
  • Ich frage mich oft, warum das gespeicherte Artefakt und die Code-Projektion, die wir tatsächlich sehen, identisch sein müssen. Schön wäre, wenn selbst git diff als IR-Projektion betrachtet werden könnte. Dank AST-Tools wie treesitter kann man sich besser vorstellen, wie Menschen AST oder IR effizienter über Interfaces bearbeiten könnten. Als Beispiel wird die ordered compilation-Struktur von f# genannt, die Code Reviews vereinfacht. In Sprachen oder Strukturen mit freier Reihenfolge muss man dagegen für einen kleinen diff an vielen Stellen hin- und herspringen, um den Gesamtkontext der Änderung zu verstehen.
  • Zu eslint-config-airbnb wird eine unangenehme Erfahrung geteilt. Genannt werden typische Probleme wie #1271 und #1122. Beim Versuch, die Airbnb-Config auf ein bestehendes Projekt anzuwenden, ging über eine Stunde mit unnötigem Herumprobieren verloren, obwohl der Code ursprünglich völlig in Ordnung war. Wegen unnötiger Regeln fühlte sich das unproduktiv an. Am Ende wurden genau diese Regeln lokal deaktiviert, und seitdem wurde die Konfiguration in keinem Projekt mehr verwendet. Dieses Beispiel zeigt, wie sehr falsche Lint-Regeln die Produktivität ruinieren können.