10 Punkte von GN⁺ 2025-08-31 | 1 Kommentare | Auf WhatsApp teilen
  • Dieses Open-Source-Projekt dokumentiert systematisch verschiedene Methoden und Beispiele, um die kognitive Last in der Softwareentwicklung zu reduzieren
  • Unnötig komplexer Code, Strukturen und Abstraktionen beeinträchtigen die Produktivität von Entwicklerinnen und Entwicklern und erhöhen die Wartungskosten
  • Bei Modulen sind nicht „kleine und flache“, sondern tiefe Strukturen mit einfachen Interfaces und starker Funktionalität wünschenswert
  • Übermäßige Abstraktion, Framework-Abhängigkeit und der missbräuchliche Einsatz des DRY-Prinzips erhöhen die kognitive Last eher noch
  • Die beste Architektur ist eine einfache Codebasis, die auch neue Entwicklerinnen und Entwickler schnell verstehen können

Projektzusammenfassung und Bedeutung

Dieses Open-Source-Material auf GitHub konzentriert sich auf eines der Grundprinzipien der Softwareentwicklung: die „kognitive Last“ (cognitive load). Die größte Stärke dieses Repositories besteht darin, die Ursachen der Komplexität, denen Entwicklerinnen und Entwickler in der Praxis tatsächlich begegnen, unabhängig von Teamgröße oder Technologietrends anhand verschiedener Beispiele und Lösungsansätze zu ordnen. Anders als viele Materialien, die sich vor allem auf Best Practices konzentrieren, berücksichtigt es auch psychische und kognitive Belastung und bietet damit konkrete Vorteile für Wartbarkeit und das Onboarding neuer Teammitglieder.

Einleitung

  • Trendige Konzepte oder Best Practices, von denen wir im Entwicklungsalltag hören, scheitern in der Praxis oft
  • Die Hauptursache für die in der täglichen Arbeit empfundene Verwirrung und die daraus entstehenden Zeit- und Kostenverluste ist hohe kognitive Last
  • Entwicklerinnen und Entwickler verbringen mehr Zeit mit dem Verstehen und Lesen von Code als mit dem Schreiben
  • Der Text konzentriert sich auf praktische Methoden zur Reduzierung unnötig entstehender kognitiver Last (Extraneous Cognitive Load)

Was ist kognitive Last?

  • Kognitive Last bezeichnet die Menge an Informationen, die eine Entwicklerin oder ein Entwickler im Kopf behalten muss, um eine Aufgabe abzuschließen
  • Im Durchschnitt können nur etwa vier „Informations-Chunks“ (Bedingungen, Variablenwerte usw.) gleichzeitig im Kurzzeitgedächtnis gehalten werden
  • Erreicht die kognitive Last einen kritischen Punkt, sinken Verständnis und Entwicklungsgeschwindigkeit deutlich

Arten kognitiver Last

  • Intrinsische kognitive Last (Intrinsic): entsteht aus der inhärenten Schwierigkeit der Aufgabe selbst. Sie lässt sich nicht reduzieren
  • Unnötige kognitive Last (Extraneous): entsteht durch die Art der Informationsvermittlung, Strukturgestaltung oder unnötige Muster als künstliche Komplexität. Sie kann aktiv reduziert werden

Praktische Beispiele und Verbesserungsansätze

Komplexe Bedingungen

  • Code mit mehreren verschachtelten Bedingungen erhöht die kognitive Last, weil man sich in jedem Schritt mehr Details merken muss
  • Lösung: aussagekräftige Zwischenvariablen einführen, um den Zweck jeder Bedingung klar zu trennen

Verschachtelte if-Anweisungen vs. Early Return

  • Im Vergleich zu verschachtelten if-Anweisungen reduziert das Muster Early Return die Last, sich Vorbedingungen merken zu müssen
  • Wenn man sich nur den „happy path“ merken muss, wird Arbeitsgedächtnis frei

Nebenwirkungen von Vererbungsstrukturen

  • Tiefe Vererbungshierarchien (z. B. KlasseA → KlasseB → KlasseC …) führen zu einer explodierenden kognitiven Last, weil man zum Verständnis des Codes viele Ebenen gleichzeitig im Kopf behalten muss
  • Lösung: Komposition bevorzugen, also Komposition statt unnötiger Vererbung einsetzen

Zu viele flache Module/Funktionen

  • Statt 80 flacher und kleiner Klassen sind einige wenige tiefe Module mit leistungsfähigen, einfachen Interfaces leichter zu warten
  • Als Beispiel wird das einfache UNIX-I/O-Interface genannt (open, read, write, lseek, close)

Missverständnisse rund um das Prinzip der „Single Responsibility“

  • Die vage Auslegung von „macht nur eine Sache“ führt eher zu vielen flachen und unklaren Abstraktionen
  • Praktisch sinnvoller ist die Interpretation als „ist gegenüber genau einer Anspruchsgruppe verantwortlich“, weil sie das Verständnis des Business-Kontexts verbessert und die kognitive Last reduziert

Missbrauch von Microservices

  • Zu viele flache Microservices zwingen dazu, Beziehungen und Integrationsinformationen aller Services ständig im Kopf zu behalten, was kognitive Last sowie Debugging- und Release-Kosten erhöht
  • Gerade anfangs ist eine gut ausgearbeitete monolithische Struktur oft wartungsfreundlicher

Zu viele Sprachfeatures/Optionen

  • Die zahlreichen neuen Sprachfeatures einer Sprache selbst (insbesondere bei C++ usw.) führen eher dazu, dass man nachvollziehen muss, warum etwas genau so implementiert wurde, wodurch sich die Gedächtnislast aufsummiert
  • Das erzeugt viel zusätzliche kognitive Last ohne Bezug zum Business

Mapping von HTTP-Statuscodes auf Business-Logik

  • Eine willkürliche Zuordnung von HTTP-Statuscodes (401, 403, 418 usw.) zu internen Business-Bedeutungen muss vom ganzen Team auswendig gelernt werden
  • Verbesserung: konsistente Verwendung selbsterklärender String-Codes (z. B. "jwt_has_expired")

Missbräuchlicher Einsatz des DRY-Prinzips (Do not repeat yourself)

  • Wenn in einer komplexen Codebasis zwanghaft Duplikate entfernt werden, entstehen starke Abhängigkeiten, die kognitive Last und Änderungskosten sogar erhöhen können
  • Zitiert wird Rob Pikes berühmte Aussage, dass lokal „ein wenig Kopieren“ besser sein kann

Schäden durch Framework-Abhängigkeit und Layered Architecture

  • Wenn man stark von den „magischen“ Strukturen eines Frameworks abhängt, brauchen neue Entwicklerinnen und Entwickler viel Zeit, um die interne Logik zu verstehen
  • Angesammelte Abstraktionsschichten lassen die kognitive Last beim Nachverfolgen realer Probleme explodieren
  • Stattdessen sollte man sich auf Grundprinzipien konzentrieren: Dependency Inversion, Information Hiding und Kontrolle kognitiver Last

Missverständnisse rund um Domain-Driven Design (DDD)

  • Der Kern von DDD ist die Analyse des Problemraums; eine Fixierung auf Ordnerstrukturen oder Muster erzeugt eher subjektive Interpretationen und kognitive Last
  • Frameworks wie Team Topologies sind wirksamer, um kognitive Last aufzuteilen

Vertrautheit vs. Einfachheit

  • Vertrautheit ist nicht dasselbe wie Einfachheit. Etwas fühlt sich nur leichter an, weil man daran gewöhnt ist; die Struktur selbst ist dadurch nicht wirklich einfach
  • Wenn neue Mitarbeitende länger als 40 Minuten verwirrt sind, ist das ein Signal dafür, dass der Code verbessert werden muss

Reale Erfolgs- und Misserfolgsbeispiele

  • Wie bei Instagram kann auch mit einer einfachen monolithischen Architektur ein hohes Maß an Skalierung und Wartbarkeit erreicht werden
  • Unternehmen, in denen „wirklich clevere Entwickler“ komplexe Strukturen gebaut haben, scheiterten dagegen häufig
  • Eine Struktur, die alle Entwicklerinnen und Entwickler leicht lesen und mit der sie sich schnell einarbeiten können, spielt eine Schlüsselrolle für höhere Produktivität

Fazit

  • Unnötige kognitive Last, die über die eigentliche Aufgabe hinausgeht, ist für alle Beteiligten in der Entwicklung schädlich
  • Der beste Code ist der, den andere Entwicklerinnen und Entwickler in Zukunft und man selbst so schnell wie möglich verstehen können
  • Statt Strukturen, die „smart aussehen“, sind gewöhnliche und direkte Lösungen langfristig vorteilhafter für Wartung und Teamproduktivität

Referenzen/Nachwort

  • Es werden auch Meinungen bekannter Entwickler wie Rob Pike, Andrej Karpathy, Elon Musk, Addy Osmani und antirez (Redis-Entwickler) zitiert
  • Die Schlussfolgerungen decken sich mit realen Großprojekten wie Chromium, Redis und Instagram
  • Einfachheit, Klarheit und die Reduzierung kognitiver Last sind der Kern nachhaltiger Software

Der Wert dieses Open-Source-Projekts

  • Material mit Fokus auf realistische Entwicklererfahrungen und praktische Beispiele, die viele Bücher über Softwaredesign oder Muster übersehen
  • Bietet sofort nutzbaren praktischen Mehrwert für unterschiedliche Teams, etwa beim Onboarding, bei Architektur-Reviews und bei langfristiger Wartung
  • Dient als Checkliste, um Code anhand des klaren Rahmens „kognitive Last“ erneut zu betrachten

1 Kommentare

 
GN⁺ 2025-08-31
Hacker-News-Kommentare
  • Das größte Aha-Erlebnis hatte ich mit dem Buch A Philosophy Of Software Design von John Ousterhout; für mich ist es das beste Buch zu diesem Thema, und ich empfehle jedem Entwickler dringend, es zu lesen. Der Kern ist, dass das Ziel beim Softwaredesign darin bestehen sollte, Komplexität zu minimieren. Komplexität wird dabei als „wie schwer ist es, Änderungen vorzunehmen“ definiert, und diese „Schwierigkeit“ wird durch die kognitive Belastung bestimmt, die beim Verstehen des Codes entsteht.

    • Das Problem ist, dass keine Regel am Ende Urteilsvermögen, Erfahrung und Intuition ersetzen kann. Jede Regel kann zum Werkzeug in einer Debatte werden, und Architekturdebatten gewinnt man nie. Das Gute an diesem Text ist, dass die Leute, die ihn nicht brauchen, das alles ohnehin schon wissen, und diejenigen, die ihn wirklich bräuchten, ihn nicht verstehen werden. Letztlich ist das kein technisches, sondern ein menschliches und kulturelles Problem. Architektur folgt am Ende aus Menschen und Kultur. So wie es Rob Pike und Google brauchte, damit Go entstehen konnte, entsteht eine Sprache wie Go nicht einfach dadurch, dass man ein Buch liest.

    • Ich denke, das DRY-Prinzip (Don’t Repeat Yourself) ist eigentlich ein Prinzip, das man erst berücksichtigen sollte, nachdem man eine Anwendung wirklich verstanden und mehrere Versionen gebaut hat. Am Anfang sollte man eher wiederholen, um zuerst den Problemraum zu verstehen, und sich in der zweiten Version Gedanken über Wartbarkeit machen. Erst etwa bei der dritten Version ist man meiner Meinung nach an dem Punkt, an dem man DRY anwenden kann.

    • Es ist unglaublich schwer, dieses Buch zu bekommen, ohne Jeff Bezos Geld zu geben. Falls jemand den Autor John kennt, sollte man ihn unbedingt auf dieses Problem hinweisen. Selbst im Campus-Buchladen gab es es nicht, und weder lokale Buchhandlungen noch Powell’s konnten es besorgen.

    • Ich habe schon vor langer Zeit aufgegeben, die perfekte Softwarelösung zu suchen. Es scheint niemanden zu geben, der alles perfekt geordnet hätte. Am Ende sind Weisheit und Erfahrung von Menschen unsere besten Werkzeuge. Kontext, Branche und Team unterscheiden sich zu stark, als dass man das sauber in Zahlen oder Gesetze fassen könnte. Mein Ziel im Design ist deshalb, ein Gleichgewicht zwischen „Chaos“ und „Schönheit“ zu finden. Am schwersten war für mich, dass das Geschäftliche unsicher ist, Software aber deterministisch; Business-Anforderungen ändern sich ständig, und es ist schwer, sie an die Starrheit von Computersystemen anzupassen. In letzter Zeit versuche ich nur dann zu refaktorieren, wenn ich beim Ändern von Code direkt Unbehagen spüre. Und selbst dann räume ich nur das Nötigste auf. Wenn man solche wiederholten, kleinen Refactorings oft genug macht, entstehen irgendwann neue Muster, die man dann als Abstraktionen herausziehen kann.

    • Dieses Buch ist genau dazu das Beste. Der betreffende Artikel wurde ebenfalls von diesem Buch inspiriert. Ich habe mit dem Autor John auch ein- oder zweimal über den Inhalt gesprochen.

  • Die Fähigkeit, Code zu schreiben, der die kognitive Belastung anderer reduziert, ist eine sehr seltene und schwierige Kompetenz. Selbst wenn man sie hat, verlangt sie ständige Anstrengung. Letztlich komprimiert ein Entwickler die Kernideen so, dass nur das Wesentliche sichtbar bleibt und nur die wirklich notwendige Komplexität offengelegt wird. In der Praxis sehe ich das fast nie gut umgesetzt.

    • Wirklich gut gemachter Code führt am Ende dazu, dass Leute sich einbilden: „War das Problem von Anfang an so einfach?“ Dagegen wird Code, bei dem die Komplexität sichtbar ist und der wie ein Kartenhaus aussieht, oft als Spur harter Arbeit anerkannt und führt sogar zu Beförderungen.

    • Das gilt genauso für Interfaces oder UX-/Interaction-Design. Entwickler können kognitive Last viel besser tragen als normale Nutzer, aber wenn man etwas bauen will, das Nicht-Techniker gut benutzen können, muss man sich von der eigenen Entwicklerintuition lösen — und genau das ist extrem schwierig. Werkzeuge so zu gestalten, dass normale Nutzer komplexe Probleme intuitiv lösen können, ist wirklich schwer.

    • Die meisten Abstraktionen überleben Anforderungsänderungen nicht gut. Die Frameworks, die ich mag, wissen, dass man nie eine für immer perfekte Abstraktionsschicht bauen kann, und bieten absichtlich „Escape Hatches“ an. (Zum Beispiel in Web-UI-Frameworks direkte Referenzen auf HTML-Elemente.) Wichtig ist die kluge Einsicht, dass man die Zukunft nicht perfekt vorhersagen kann.

    • In vielen Firmen ist diese Fähigkeit in der Praxis weniger zwingend notwendig als eher ein Bonus. Ein Blick auf die wichtigsten Codebasen reicht, um das zu sehen.

  • Ich halte mich selbst für einen der „schlauen Entwickler mit Nerd-Tendenz“. Ich baue gerne Abstraktionen. Deshalb finde ich es zugleich faszinierend und beunruhigend, dass die Branche sich derzeit in Richtung einer „Architektur aus einem Haufen if-Anweisungen“ bewegt. Ich verstehe, warum viele das mögen: Es wirkt einfach, ist leicht zu verstehen und man kann einfach das gegebene Ticket schließen. Die meisten Entwicklungsprozesse stützen sich auf solche if-Anweisungshaufen, und ab einer gewissen Größenordnung funktioniert dieser Ansatz tatsächlich recht gut. Selbst wenn es zu massiven Datenschutzlecks kommt, wird oft kaum jemand zur Verantwortung gezogen. Das Problem ist nur, dass ich nicht weiß, ob es überhaupt eine bessere Alternative gibt. Schicke Abstraktionen oder elegante Architektur scheinen die Konsistenz des Codes in der Praxis auch nicht wirklich zu verbessern. Besonders im Unternehmensumfeld lässt sich vorsichtig schöne Abstraktion kaum bauen, weil die Eigentümer der Business-Logik sich fast nie wirklich um die Logik kümmern. Am Ende gibt es erst eine Anforderung wie „Bestellungen werden nur an eine Adresse geliefert“, und plötzlich heißt es: „Ein großer Kunde will an mehrere Adressen liefern lassen.“ In einem solchen Chaos ist eine fehlerfreie Abstraktion kaum möglich. Ich frage mich inzwischen ernsthaft, ob ein Haufen if-Anweisungen für Unternehmenssoftware nicht die realistisch beste Lösung ist.

    • Auf die Frage, ob der „Haufen if-Anweisungen“ die beste Lösung sei, empfehle ich das Big Ball of Mud paper über reale große Softwarearchitekturen und die Zusammenfassung. Reale Systeme entwickeln sich immer weiter: Sie beginnen oft als „Schlammball“, verbessern sich bereichsweise, und wenn wieder Veränderungen kommen, brechen selbst schöne Abstraktionen zusammen. Der Kern ist, Systeme wachsen zu lassen wie eine kleine Stadt, die zu einer Großstadt wird — durch eine Mischung aus Domänenmodellierung, angemessener Abstraktion und den nötigen destruktiven Veränderungen.

    • Auch in solcher Software kann man großartige Abstraktionen schaffen, aber sobald Business-Logik ins Spiel kommt, wird es schwer, sie zu erhalten. Die Teile, in denen Abstraktion gut bestehen bleibt, sind meist produktnahe Aspekte wie Authentifizierung, Berechtigungen, Logs, Datenbanken, Middleware oder Infrastruktur. Sobald interne Business-Logik beginnt, die Abstraktion zu beeinflussen, endet alles wieder im Chaos. An manchen Orten hat man sogar versucht, die Logik direkt von Fachbereichen verwalten zu lassen; dadurch wurde alles schwer testbar, unverständlich und sogar Simulationen waren unmöglich. Am Ende brauchte man dann Operatoren, und Junior-Entwickler schrieben Code über grafische Tools. Selbst nach mehreren Rewrites ist nach zwei bis drei Jahren alles wieder durcheinander.

    • Für Fachbereiche ist es absolut unmöglich, den Implementierenden Business-Logik perfekt zu erklären. Selbst wenn sie sie für sich selbst verstehen, können sie sie nicht in einer Form ausdrücken, die sich aus Coding-Sicht direkt umsetzen lässt. Vielmehr muss mindestens ein Implementierender die Nutzer wirklich bis ins Mark selbst erleben, um sie richtig zu verstehen. In der Praxis erzwingen Unternehmen aber organisatorische Trennung, und „Business-Logik“ wird zu einem Bereich, um den sich niemand richtig kümmert — am Ende manipuliert man nur noch if-Anweisungen.

    • Der entscheidende Punkt ist, dass die Realität selbst, also das Business an sich, bereits ein Haufen if-Anweisungen ist. Wenn das Problem oder die Domäne klar technisch oder verallgemeinerbar ist, kann man mit Abstraktionen if-Anweisungen reduzieren. Wenn aber die Domäne selbst chaotisch ist, muss auch die Abstraktion letztlich „Flexibilität“ von Anfang an eingebaut haben. Widersprüche können dann sogar zu einem Feature werden.

    • Wenn man mit Tools wie Codex CLI herumspielt, sieht man: Trifft das Tool auf einen Bug, erzeugt es immer einen if-Patch für genau diesen Sonderfall. Wenn man ihm nicht ausdrücklich Muster beibringt und nach einer neuen Abstraktion fragt, fügt es immer weiter if-Anweisungen hinzu, die es dann „Heuristiken“ nennt. Für zehn Bugs eines bestimmten Typs entstehen zehn Patches, und wenn dann der elfte ähnliche Bug auftaucht, funktioniert das natürlich nicht mehr. Die von Codex vorgeschlagene Lösung ist also letztlich eine Ansammlung wiederholter if-Anweisungen.

  • Ich frage mich, wie häufig es in der Realität wirklich vorkommt, dass man in einem völlig unbekannten Projekt Änderungen vornehmen soll. Wenn man nicht ständig zwischen Projekten wechselt, passiert das vielleicht einmal in zwei Jahren. Ich denke, es ist besser, sich auf wirklich schwierige Probleme zu konzentrieren statt auf bloßen Erfahrungsmangel.

  • Ich habe acht Jahre in der Entwicklerorganisation von Microsoft gearbeitet, und dort war ein frühes Modell von Ingenieurstypen sehr nützlich. Es gab drei Personas, die später durch ein komplexeres Framework ersetzt wurden. Trotzdem haben mir die ursprünglichen Personas bis heute in meiner Karriere stark geholfen, effektiv mit anderen Ingenieuren zu kommunizieren.

    • Mort: pragmatischer Ingenieur, Business-Ergebnis hat oberste Priorität. Ein Haufen if-Anweisungen reicht völlig, solange es schnell funktioniert.
    • Elvis: Innovation zuerst, neueste Technologien einsetzen, will, dass sein eigenes Genie sichtbar wird. Besessen von neuen Frameworks, instabilem Code, Sichtbarkeit und Innovation.
    • Einstein: fixiert auf Performance, Eleganz und technische Korrektheit. Legt mehr Wert auf Konsistenz im Code und technische Vollendung. In der Realität ist jeder Ingenieur eine Mischung aus allen drei. Nach ein paar PRs und Design-Reviews kann man die dominante Tendenz meist grob erkennen.
    • Ich finde, es sollte noch einen Ingenieurstyp Amanda geben. Nach zwanzig Jahren, in denen sie ihren eigenen und fremden chaotischen Code reviewt hat, hat sie verinnerlicht, dass Code vor allem dafür da ist, von Menschen gelesen zu werden. Ich würde am liebsten nur mit solchen Amandas ein Team aufbauen.

    • Mort ist der Pragmatiker, Einstein der Perfektionist, und Elvis ist ... ehrlich gesagt eher ein Schaden für Projekte. Ein bisschen kann er motivierend wirken, aber das ideale Team ist eine gute Mischung aus Mort und Einstein. Es muss so einfach wie nötig sein und zugleich präzise genug, damit Wartung nicht zur Qual wird. Tatsächlich beginnt sogar Mort, wenn man ihm lange genug ein Langzeitprojekt überlässt, irgendwann wie Einstein auf diese Dinge zu achten. Nebenbei: Die automatischen Coding-Agenten der letzten Zeit haben viel zu starke Mort-Tendenzen, sodass ich sie inzwischen fast wie ein Mort managen muss.

    • Personas sind ein gutes Werkzeug. Meiner Erfahrung nach verkommen sie mit der Zeit allerdings zu falschen Abkürzungen. Elvis war in Wirklichkeit eher ein interner politischer Begriff, und wie bei Goodharts Gesetz sah alles logisch korrekt aus, also wollte jeder es in Debatten einsetzen — dadurch verlor es seine Nützlichkeit. Alan Cooper hat das Persona-Konzept damals zusammen mit der Visual-Basic-Entwicklung eingeführt. Wichtig ist zu verstehen, dass andere Perspektiven, etwa von Wissenschaftlern und Firmware-Entwicklern, unterschiedliche Wertesysteme haben. Passendes Buch

    • Die besten Ingenieure sind meiner Ansicht nach diejenigen, die alle drei Tendenzen je nach Projekt, Situation und persönlichen Zielen austarieren können. Je nach Rolle braucht man andere Gewichtungen. Für Compiler-Optimierung braucht man zum Beispiel mehr Einstein und Mort, während bei Code wie einer Game Engine das Verhältnis anders ist. Darüber, ob die Merkmale selbst exakt stimmen, kann man diskutieren, aber entscheidend ist, dass alle sich im Lauf der Zeit unterschiedlich verhalten müssen.

    • Ich finde, dieser Ansatz braucht Grenzen. Menschen zu stark in einfache Kategorien zu pressen, kann unfair sein und zu dauerhafter Stigmatisierung führen. Meiner Erfahrung nach bevorzugt das Management eher Mort als Elvis. Die eigentliche Lösung liegt meiner Ansicht nach in Leadership und Management. Wenn man bei Mort Codequalitätsstandards in die Anforderungen aufnimmt, liefert er auch dann ordentliche Ergebnisse, wenn es etwas langsamer geht. Elvis braucht Grenzen, und Einsteins müssen pragmatische Deadlines klar vorgegeben bekommen. Dieser Ansatz hat allerdings die Grenze, dass er die Komplexität des Menschen übersieht.

  • Ich mache mir Sorgen, dass AI der Softwareindustrie schaden könnte. AI hat nicht dieselben menschlichen Grenzen und kann extrem komplexen, schwer lesbaren, aber funktionierenden Code schreiben — und wenn dieser am Ende kaputtgeht, kann ihn womöglich niemand mehr reparieren. Deshalb rate ich Junior-Ingenieuren, sich nicht nur auf AI zu verlassen, sondern die Eigenheiten der Codebasis wirklich kennenzulernen. Sonst verlieren sie die Fähigkeit, selbst Code zu schreiben.

    • Ich finde dieses Argument nicht überzeugend, weil AI den Code auch wieder reparieren kann, wenn er nicht mehr funktioniert.

    • Nach meiner Erfahrung sollte man AI so lange auffordern, ihren Code zu vereinfachen, bis man ihn wirklich verstehen kann. Wenn die Lösung zu kompliziert ist, soll sie einfacher werden; wenn unnötige externe Bibliotheken verwendet werden, sollen sie entfernt werden; idealerweise mit der Standardbibliothek oder nur bereits vorhandenen Abhängigkeiten. AI schreibt den Code für mich, nicht für sich selbst.

    • Im Gegenteil könnte AI die Softwarequalität sogar erhöhen, weil sie die kognitive Belastung des Low-Level-Designs reduziert und man sich dadurch stärker auf die übergeordnete Architektur konzentrieren kann.

  • Zu der im Artikel erwähnten „typischen Angewohnheit smarter Entwickler“: Es wirkt, als meine der Autor damit, dass er nur Code versteht, den er selbst geschrieben hat oder der seinem Stil entspricht. Aber der wahre Schlüssel zur Reduktion kognitiver Last ist, die Menge an Code zu minimieren, die man überhaupt lesen muss. Starke Grenzen und klare APIs machen Änderungen leichter; entscheidend ist nicht der gesamte Code, sondern nur die aus sauber definierten Interfaces abgeleitete Komplexität, um die man sich kümmern muss. Die Eigenart des „smarten Entwicklers“ ist eher ein oberflächliches Problem.

    • Genau darin liegt meiner Meinung nach der größte Vorteil des Microservices-Konzepts. Wenn zwei Teams ausschließlich über APIs kommunizieren und die Grenzen mit Werkzeugen wie Schemas strikt definieren, werden sie bei Änderungen extrem konservativ und denken im Vorfeld viel gründlicher nach. Es ist, als würde man technisch absichtlich Reibung an den Stellen einbauen, von denen man hofft, dass sie sich nicht ändern.

    • Beim Debuggen habe ich oft gemerkt, wie ermüdend es ist, wenn Teile des Codes zu stark auf direkte Debugbarkeit im Call Stack optimiert sind. Deshalb extrahiere ich bestimmte Teile lieber in Funktionen und teile Commits auf; so lassen sich ungewollte Codeänderungen leichter zurückrollen und der Fokus im Code wird besser. Im PR landet es zwar am Ende auf einmal, aber mit klaren Grenzen ist es trotzdem viel besser.

    • Entwickler sind im Allgemeinen nicht besonders gut darin, in „Verträgen und Interfaces“ zu denken. Man sollte sie dazu bringen, nur auf die nach außen sichtbaren Zusagen zu schauen, nicht auf die interne Implementierung. Das Ziel ist, dass etwas verständlich ist, ohne den Code lesen zu müssen. Wenn jemand meinen Code verstehen will und dafür hineinschauen muss, habe ich versagt.

    • Selbst wenn eine API noch so klar ist, kann der interne Code trotzdem schwer verständlich sein. Nach außen scheint alles sauber zu funktionieren, aber in der Realität muss man oft doch in die Interna eintauchen.

  • Ich mag diesen Artikel sehr, weil er meine Erfahrung extrem gut zusammenfasst. Die meisten Programmiermethodologien, die ich offiziell gelernt habe, schlagen in dem Moment ins Gegenteil um, in dem jemand anders meinen Code lesen muss. Code, der Dinge wie in Rust und C++ stark versteckt, ist anstrengend; wenn ich dagegen C sehe, wo man Code nicht hinter sechs Schichten Templates verstecken kann, ist das fast schon beruhigend.

    • Schön zu hören, dass das mit deinen Erfahrungen übereinstimmt. Ich mochte C aus genau diesem Grund ebenfalls, bin in letzter Zeit aber zu Golang gewechselt und schätze dort dieselbe Einfachheit.
  • Die Aussage, dass Code-Zugänglichkeit wie ein Bürger erster Klasse behandelt werden muss, trifft für mich voll ins Schwarze. Regeln sollte man als Leitlinien sehen, und wirklich gute Leute haben die Fähigkeit, je nach Kontext zu entscheiden, wann man Regeln brechen oder ergänzen sollte, damit Code leicht lesbar bleibt. Letztlich ist die Fähigkeit wichtig, die kognitive Last von Code und die nötigen Trade-offs intuitiv zu spüren. Ob Duplikation oder Abstraktion — man muss immer die nächste Person im Blick haben, einschließlich des eigenen Ichs in sechs Monaten. Auf die Forderung, noch eine weitere Regel einzuführen, würde ich sagen: Das ist nur die Wiederholung desselben Problems. Nach grundlegenden Leitlinien geht es um tacit knowledge, also implizites Wissen aus Erfahrung. Mit der Zeit entwickelt man ein Gefühl dafür, welcher Code gut und welcher schlecht ist. Am Ende muss man es direkt selbst erfahren.

    • Ich stimme dem Kern von Code-Zugänglichkeit zu, finde aber schade, dass der Autor germane overhead (den Verbrauch kognitiver Ressourcen auf Empfängerseite) übergeht. Um Code-Zugänglichkeit wirklich zu erhöhen, muss man letztlich alle drei Arten von Overhead berücksichtigen: intrinsic, extraneous und germane.
  • Oft hört man, man solle das „Warum“ dokumentieren, aber ich finde es schwer, „Warum“ und „Was“ sauber zu trennen, also halte ich beides fest. Der schlechteste Kommentar ist etwa:

    x = 4 // assign 4 to x
    

    So etwas. Wenn man Code und Kommentare vermischt, wird alles schwerer lesbar und der Kontextwechsel ist groß. Besser ist so etwas:

    // Warum wir das tun, und was gleich passieren wird
    setup();
    t = setupThing();
    t.useThing(42);
    t.theWidget(need=true);
    ...
    

    Kommentare und Code also klar trennen. Trotzdem ist selbst ein Kommentar zum „Was“ viel besser als gar nichts und reduziert die kognitive Last.

    • Solche Kommentare sind meistens schwer zu pflegen, und weil sich die Implementierung in einem Jahr fünfmal ändert, altern sie schnell und stiften Verwirrung. In meinen letzten Projekten habe ich fast alle Kommentare entfernt und nur wirklich schwierige Logik und Dokumentation auf oberster Ebene belassen.

    • Ich denke, es gibt Fälle, in denen man beides dokumentieren sollte — why und what. Manchmal muss man den Grund erklären, manchmal das Verhalten klar benennen. Ich finde, der Wert von Kommentaren wird heute unterschätzt. Man muss nicht jede Zeile kommentieren, aber die meisten „selbstdokumentierenden“ Codes sind auch nicht besonders leicht zu lesen.

    • Für mich ist heute am schwierigsten zu entscheiden, was in den Code gehört und was in Design-Dokumente oder technische Dokumentation. Mein Fazit ist, dass Kommentare im Code am besten dafür genutzt werden sollten, nicht intuitive oder verborgene Absichten zu erklären. Zum Beispiel: „Der Grund für dieses Memoizing ist X.“

    • Über Kommentare im Stil von ChatGPT wie x=4 musste ich lachen. Der Nachteil des vorgeschlagenen Stils ist allerdings, dass Kommentare veralten und nicht mehr zum Code passen können. Wenn man den Code ändert, muss man die Kommentare unbedingt mit aktualisieren.

    • Ich bin kein ausgebildeter Programmierer, sondern Physiker, und versuche deshalb beim Kommentieren jedes Mal, stärker in diese Richtung zu gehen. Als Student war es üblich, für gute Noten einfach so viele Kommentare wie möglich zu schreiben.