1 Punkte von GN⁺ 2025-01-12 | 1 Kommentare | Auf WhatsApp teilen
  • Der Makefile-Effekt bezeichnet das Muster, bei dem man ein komplexes oder ungewohntes Tool nicht von Grund auf neu verwendet, sondern eine früher gut funktionierende Konfiguration kopiert und für eine neue Situation anpasst.
  • In der Problemlösungsphase kann das Wiederverwenden bewährter Beispiele eine vernünftige technische Reaktion sein, weil es das Bug-Risiko senkt.
  • Aus Designperspektive kann es jedoch als Usability-Signal gesehen werden: Das Tool ist von Anfang an schwer oder lästig zu benutzen, sodass sich Änderungen immer weiter auf Kopien ansammeln.
  • Ähnliche Abläufe aus Kopieren und Anpassen zeigen sich nicht nur bei Make, sondern auch bei GitHub Actions, GitLab CI/CD, Linter- und Formatter-Konfigurationen sowie in Build-Systemen.
  • Tool-Designer sollten prüfen, ob Konfiguration und eine eigene Syntax wirklich nötig sind, ob sich vertraute CLI-Idiome wiederverwenden lassen und ob Nutzer am Ende auf Copy-and-paste angewiesen sind.

Was ist der Makefile-Effekt?

  • Der Makefile-Effekt beschreibt das Phänomen, dass ein Tool mit einem gewissen Maß an Komplexität oder Unvertrautheit nicht neu geschrieben wird, sondern ein früheres „funktionierendes“ Beispiel kopiert und angepasst wird.
  • Der typische Ablauf sieht so aus:
    • Eine häufige Art von Aufgabe muss erledigt werden, und eine sehr ähnliche oder identische Aufgabe wurde bereits früher ausgeführt.
    • Make oder ein ähnliches Tool wird als passendes Werkzeug für diese Aufgabe ausgewählt.
    • Statt ein neues Makefile zu schreiben, kopiert der Engineer das Makefile einer früheren Aufgabe und korrigiert es, bis es in der neuen Umgebung funktioniert.
  • Make ist nur das bekannteste Beispiel. Da Teams und Einzelpersonen unterschiedliche Tools beherrschen, sind manche Tool-Kategorien anfälliger für diesen Effekt als andere.
  • Der scherzhafte Ausdruck „heritage Makefile“ bezeichnet eine Situation, in der ein von Senior Engineers, Professoren oder anderen überliefertes Makefile mit nur kleinen Änderungen immer weiter vererbt wird.

Welche Probleme wiederholtes Kopieren im Tool-Design sichtbar macht

  • Wenn ein Problem sofort gelöst werden muss, kann das Wiederverwenden eines funktionierenden Beispiels eine knappe und sinnvolle Wahl sein.
    • Da sich der Großteil der Aufgabe nicht ändert, entstehen theoretisch auch weniger neue Bugs.
    • Der Makefile-Effekt ist nicht von Natur aus schlecht oder ineffizient.
  • Aus Designsicht ist er jedoch ein Signal dafür, dass das Tool oder seine Verwendung zu komplex oder umständlich ist.
    • Nutzer lösen das Problem nicht von Grund auf, sondern kopieren bestehende Lösungen immer wieder.
    • Tritt dieser Effekt schon bei einfachen Anwendungsfällen auf, ist das Tool für diesen Zweck womöglich übermäßig komplex.
  • Dieses Muster zeigt sich auch bei anderen konfigurationszentrierten Tools außerhalb von Make.
    • Bei CI/CD-Konfigurationen wird YAML für GitHub Actions oder GitLab CI/CD oft aus der zuletzt funktionierenden Konfiguration kopiert und durch wiederholtes Ausführen angepasst.
    • Konfigurationen für Linter und Formatter werden als Grundregel-Sets zwischen Projekten kopiert und je nach lokalen Bedingungen verschärft oder gelockert.
    • Nicht triviale Konfigurationen von Build-Systemen neigen dazu, früheren Build-Systemen ähnlich zu werden.

Kosten für Lernen, Debugging und Sicherheit

  • Tools mit starkem Makefile-Effekt können breiteres Lernen behindern.
    • Einige wenige Expertinnen und Experten konfigurieren das Tool, während der Rest nur die nötigen Teile versteht und durch Kopieren und Anpassen arbeitet.
    • Der Abhängigkeitsgraph eines Build-Systems ist inhärente Komplexität, aber sich in Make den Unterschied zwischen $< und $^ merken zu müssen, ist es nicht.
  • Fehlt es an Unterstützung für Diagnose und Debugging, verlassen sich Nutzer darauf, das Tool mehrfach auszuführen und dabei nur kleine Hinweise zu erhalten.
    • In CI/CD endet das oft bei print-basiertem Debugging über Netzwerke und zwischengeschaltete VM-Orchestrierungsebenen hinweg.
  • Auch aus Sicherheitsperspektive können die Risiken steigen.
    • Sicherheitsmaßnahmen verlangen oft ein tiefes Verständnis des „Warum“ hinter einem Verhalten.
    • Systeme, in denen der Makefile-Effekt auftritt, erlauben häufig Verwechslungen zwischen Code und Daten oder allgemein Verwechslungen durch In-Band-Signalisierung (in-band signaling).
    • Ein typisches Beispiel ist template injection in GitHub Actions.

Fragen, die Tool-Designer sich stellen sollten

  • Beim Bau neuer Tools sollte man prüfen, ob Nutzer etwas von Grund auf schreiben können oder ob sie erst ein „funktionierendes Beispiel“ finden und kopieren müssen.
  • Nützliche Fragen dabei sind:
    • Ist Konfigurierbarkeit wirklich notwendig?
    • Ist eine eigene Syntax wirklich nötig?
    • Lassen sich vertraute Syntax und Idiome aus anderen Tools oder der CLI wiederverwenden?
    • Muss sogar der Ersteller selbst die Verwendung per Copy-and-paste übernehmen, und wenn ja, ist das bei anderen Nutzern wahrscheinlich ebenso?
  • Zum Begriff „cargo cult“ behandelt Ken Shirriffs Text das Problem, dass es sich um einen unangemessenen Fachbegriff handelt.

1 Kommentare

 
GN⁺ 2025-01-12
Meinungen auf Hacker News
  • „Ein komplexes System, das funktioniert, erweist sich ausnahmslos als aus einem einfachen System hervorgegangen, das funktioniert hat. Ein komplexes System, das von Grund auf entworfen wurde, funktioniert niemals und lässt sich auch nicht so reparieren, dass es funktioniert. Man muss wieder mit einem einfachen System beginnen, das funktioniert.“
    — John Gall (1975), Systemantics: How Systems Really Work and How They Fail
    https://en.wikipedia.org/wiki/John_Gall_(author)#Gall's_law

    • Deshalb bin ich gegenüber neuen Sprachen und Frameworks immer skeptisch. Auf PowerPoint-Folien sehen sie toll aus, aber wie sie in einem komplexen, langfristig gepflegten System aussehen, ist unklar.
      Meist beginnen sich Funktionen wie Kratzer anzusammeln, um Sonderfälle zu behandeln, und das wirkt wie ein Signal dafür, dass solche Ausnahmen auch künftig endlos zunehmen werden.
      Zwischen „Erfahrung anwenden“ und „ein völlig neues System um eine persönlich störende Sache herum entwerfen“ gibt es einen feinen, aber wichtigen Unterschied.
  • Ich habe eine andere Hypothese. Etwa 10 % der Entwickler verstehen die Prinzipien wirklich und können etwas von Grund auf beginnen, und weitere 40 % können mit Copy-and-paste aus lokalem Code, Stack Overflow, GitHub und LLMs ihre Alltagsarbeit erledigen und wissen grob, was passiert.
    Die übrigen 50 % wissen über ein paar LeetCode-Rätsel hinaus nicht viel und haben auch kein echtes Verständnis dafür, was sie kopieren und einfügen.
    Bei so einer Verteilung ist es sehr wahrscheinlich, dass mehr als die Hälfte aller Makefiles aus grob funktionierenden Copy-and-paste-Schnipseln besteht. Wenn sie von irgendwoher stammen, wo sie bereits funktioniert haben, ist die Aufgabe erst einmal erledigt, und man geht zum nächsten Ticket über.
    Ich gebe nicht dem Tool selbst die Schuld. Makefiles sind gut bekannt und bei kleinen Projekten auch nicht geschwätzig. Für ein Monster mit 10.000 Dateien können sie eine schlechte Wahl sein, aber ich habe auch in riesigen Projekten saubere Makefiles gesehen. Persönlich wären sie nicht meine erste Wahl, aber ich mag Makefiles und habe sie seit über 30 Jahren immer wieder verwendet.

    • Was Menschen nicht wissen, liegt meiner Meinung nach oft daran, dass sie keine Zeit haben, es herauszufinden. Die Zahl der Kämpfe, die man an einem Tag austragen kann, ist begrenzt.
      Wenn zum Beispiel ein C++-Programmierer ein Ticket bearbeitet: Bis zu wie vielen Schichten des Stacks muss er Bescheid wissen? Muss er die Namen der CPU-Register kennen? Was muss ein KI-Forscher wissen, der nur Jupyter verwendet? Es ist empfehlenswert, die Tools und den Stack so gut wie möglich zu lernen, aber die Zeit ist begrenzt.
    • Ein sehr einfaches Makefile auch in einem Projekt mit 10.000 Dateien zu verwenden, ist tatsächlich eine Kleinigkeit. Die meisten Makefiles, die ich in Open-Source-Projekten gesehen habe, waren viel komplexer als gute Makefiles.
      Wenn ich in einem Makefile eine eigene Regel zum Erzeugen einer einzelnen Datei sehe, halte ich das fast immer für einen Fehler.
      Normalerweise sollte es nur allgemeine Build-Regeln geben, mit denen alle Dateien eines bestimmten Typs gebaut werden.
      In ein Makefile sollten kaum Listen von Quelldateien oder Abhängigkeiten gehören, sondern nur Listen der Verzeichnisse, in denen sich Quelldateien befinden.
      Make sollte die Quellverzeichnisse durchsuchen, Dateien finden, sie nach Typ klassifizieren, Abhängigkeitslisten erzeugen und die passenden Build-Regeln aufrufen. Zumindest mit GNU make ist das sehr einfach und steht auch im Benutzerhandbuch.
      Wenn man es so schreibt, ist der Aufwand, ein Makefile zu erstellen oder zu ändern, gleichermaßen vernachlässigbar, egal ob das Projekt 1 oder 10.000 Dateien hat. Man muss das Makefile auch nicht jedes Mal aktualisieren, wenn Quelldateien erzeugt, umbenannt, verschoben oder gelöscht werden.
    • Ich mag Makefiles, nutze sie aber nur für persönliche Zwecke. Jedes Mal, wenn ich ein neues persönliches Projekt anlege, füge ich im Root ein Makefile hinzu, selbst wenn das Ziel nur der grundlegendste Build für die jeweilige Sprache ist.
      Denn jede Sprache und jedes Framework hat eine andere Build-„Reihenfolge“, und ich kann sie mir nicht alle merken. Aber $ make ist einfach.
    • Etwas konfigurieren zu können und wirklich zu verstehen, wie es funktioniert, sind meiner Meinung nach ziemlich unterschiedliche Dinge.
      Ich stimme zu, dass viele produktive App-Entwickler ein neues Projekt vielleicht nicht von Grund auf einrichten können, aber oft geht es dabei eher darum, die richtigen magischen Regeln und Zaubersprüche zu kennen, mit denen mehrere Tools sauber ineinandergreifen, als um tiefes Verständnis.
  • Ein weiterer Faktor, den ich am Arbeitsplatz gesehen habe, sind Tools und Systeme, mit denen Entwickler irgendwann umgehen müssen, die sie im Alltag aber für wenig lernenswert halten.
    Beispiele sind Build-Systeme und CI-Konfigurationen. Sie sind zwar unverzichtbar, aber Entwickler haben nicht das Gefühl, sich täglich damit befassen zu müssen. CI wird als ein System betrachtet, das man „einrichtet und vergisst“, und es kommt die Reaktion: Muss ich das alles lernen, nur um die App zu bauen?
    Entwickler erwarten, dass es „einfach funktioniert“, und wenn es komplex wird, geht man davon aus, dass ein anderes Team, also jemand in einer Rolle wie meiner, sich darum kümmert. Deshalb ist der Anreiz groß, jedes Mal, wenn ein Entwickler dieses System anfassen muss, die zuletzt funktionierende Konfiguration zu kopieren und dann zur „eigentlichen“ Arbeit zurückzukehren.
    Die beste Lösung ist, den Entwicklern auf halbem Weg entgegenzukommen. Man sollte je nach Aufgabe einfache oder komplexe Tools bereitstellen, Dokumentation anbieten und den Glauben an „Magie“ minimieren. Tools wie Make scheitern an dieser Stelle eher, weil sie zu komplex wirken und sich wie eine Blackbox anfühlen.

    • Das große Problem bei CI-Konfigurationen ist meiner Ansicht nach meist Folgendes: Sie sind langsam, proprietär, arbeiten mit Secrets, sodass nur wenige Leute daran arbeiten können, und lassen sich im Allgemeinen nicht lokal ausführen.
      Dadurch werden Feedback-Zyklen extrem lang, und die Arbeit selbst wird sehr schmerzhaft.
    • Der beste Ablauf, den ich gesehen habe, war, CI/CD als sehr dünnen Wrapper um Skripte oder ein Makefile im Repository zu verwenden.
      Wenn Entwickler Teile oder die Gesamtheit der „CI/CD“-Aufgaben lokal ausführen können, können sie sie sehen, steuern und verstehen. Das hilft enorm, ihnen ein Gefühl von Ownership und Sicherheit zu geben, statt dass „CI/CD etwas aus einer anderen Welt“ ist.
      Es funktioniert nicht immer. Ich habe einmal ein Zweierteam erlebt, das trotz einer dünnen Wrapper-CI/CD so tat, als sei es ein außerirdischer Prozess, und sich weigerte, ihn anzufassen.
    • Auch die Kaffeemaschine im Büro ist kein Ding, das man „einrichtet und vergisst“, aber man erwartet nicht, dass alle, die sie benutzen, die Wartungsverantwortung exakt gleich aufteilen.
      Genauso braucht CI Ownership, und es ist keine effiziente Arbeitsweise, wenn die Verantwortung beim letzten Entwickler landet, der gerade CI benutzen wollte.
    • Make ist eines der einfachsten Build-Tools. Verglichen mit Dingen wie Grunt oder Webpack ist es eher ein Hammer als ein Bohrgerät für den Bergbau.
      Die Lösung besteht darin, nicht einfach die Tools großer Unternehmen zu übernehmen, nur weil große Unternehmen sie verwenden. Das ist vermutlich eine unpopuläre Meinung, aber ich glaube, dass CI/CD an den meisten Stellen, an denen es eingesetzt wird, nicht nötig ist.
      Man sollte Wege finden, Build und Deployment mit einem absoluten Minimum an beweglichen Teilen umzusetzen, auch wenn dadurch ein paar Schritte mehr entstehen. Danach sollte man sorgfältig die Kosten abwägen, welche Teile automatisiert werden sollen. Für einfache Aufgaben große Systeme einzuführen, ist langfristig meist nicht lohnend.
      Wenn man CI/CD wirklich braucht, merkt man das an konkreten Schmerzpunkten. Wenn dieses System den Entwicklern Schmerzen bereitet, ist es nicht das richtige Tool.
    • Wenn sich make „zu komplex und wie eine Blackbox“ anfühlt, hat man cmake offenbar noch nicht gesehen.
  • Make und Makefiles sind enorm simpel, sofern sie nicht automatisch von autoconf generiert wurden. Wenn sie von autoconf erzeugt wurden, sollte man sie nicht ändern; sie sind ein Build-Artefakt. Wenn möglich, sollte man auch autoconf loswerden.
    Allgemeiner betrachtet gibt es diesen Effekt tatsächlich. Man kann ihm zum Opfer fallen oder ihn nutzen. Nutzen kann man ihn so: Man schreibt ein wenig Code oder kopiert ihn irgendwoher, probiert ihn im Projekt aus und passt ihn nach Bedarf an. Beim nächsten Projekt kopiert man diesen Code erneut hinein und verändert ihn passend für das zweite Projekt. Dann prüft man, ob sich die Änderungen auch in das ursprüngliche Projekt zurückübertragen lassen. Wenn beides funktioniert und synchron bleibt, extrahiert man den Code und macht daraus eine Library. Manchmal braucht es weitere Projekte, um ihn in eine wirklich libraryartige Form zu bringen. Im besten Fall veröffentlicht man ihn als Open Source, damit andere ihn ebenfalls nutzen können.

    • Makefiles sind außerdem extrem eingeschränkt. Zeitstempelbasierte Aktualitätsprüfung bricht in modernen Versionsverwaltungssystemen häufig.
      Git speichert intern keine Zeitstempel, daher kann die mtime einer Datei aktualisiert werden, obwohl der Inhalt identisch ist; in der Praxis passiert das oft und führt zu unnötigen Rebuilds.
      Moderne Tools, bei denen Eingabe oder Ausgabe ein ganzes Verzeichnis ist, oder Tools, bei denen die Namen der Ausgaben vor der Ausführung nicht bekannt sind, kann Make ebenfalls überhaupt nicht richtig handhaben.
      Ich mag make, habe es trotz seiner Nachteile gut genutzt und kenne Workarounds und sogar Workarounds für diese Workarounds. Aber sobald ein Tool nicht mehr perfekt zu den Erwartungen von make passt, steigen Schwierigkeit und Komplexität, ein korrektes Makefile zu schreiben, sehr schnell an.
    • Makefiles sind simpel, aber sehr häufig falsch. Ein Makefile zu schreiben, das auch in Situationen korrekt funktioniert, in denen man nicht „von Grund auf baut“, ist erstaunlich schwierig.
      Das ist kein Witz. Allein die Existenz des Konzepts make clean ist der entscheidende Beweis.
  • Makefiles sind vermutlich eine unpassende Analogie. Das Problem, das die meisten Menschen mit Makefiles haben, liegt darin, dass sie sie zu selten schreiben. Sie haben ein allgemeines Gefühl dafür, was make tut, aber keine Muscle Memory, um sie von Grund auf zu schreiben.
    Der Kernpunkt stimmt trotzdem. Ich habe oft gesehen, dass aus dem Web kopierter Code voller totem Code ist, der tatsächlich nicht verwendet wird. Eine gute Gewohnheit ist, so lange weiter zu löschen, bis etwas kaputtgeht, und dann nur den kaputtgegangenen Teil zurückzunehmen. Man sollte so viel wie möglich löschen, und alles, was aktuell nicht verwendet wird, definitiv entfernen.

    • Dasselbe Problem tritt bei vielen Tools auf, etwa Makefiles, KVM-Konfigurationen, Docker-Setups und CI/CD-Pipelines.
      Meine bisherige Lösung war, ein separates Repository mit Notizen und Beispielprogrammen als Shell-Skripte zu solchen Tools, Libraries und Frameworks anzulegen.
      Jedes Mal, wenn ich ein Tool wieder verwenden muss, frische ich anhand der Notizen mein Gedächtnis auf, und wenn ich etwas Neues lerne, aktualisiere ich die Notizen. Inzwischen kann ich auch ein LLM auf dieses Repository verweisen und Fragen stellen.
      Dieses Repository ist privat und enthält Informationen zu öffentlich verfügbaren Tools. Organisationsspezifisches Wissen liegt in einem ähnlichen, aber separaten Repository und wird gelöscht, wenn der Vertrag mit dem Kunden oder Arbeitgeber endet.
  • Der treffendste Begriff dafür ist Cargo-Cult-Entwicklung. Cargo-Kulte entstanden im Pazifik während des Zweiten Weltkriegs: Einheimische Inselbewohner sahen die wundersamen Flugzeuge, die Lebensmittel, Alkohol und Vorräte brachten, ahmten die Handlungen der Soldaten nach und beteten, dass Bambusflugzeuge und Kokosnuss-Apparate die Götter beeindrucken und die Lieferungen zurückbringen würden.
    Das Problem war, dass die Inselbewohner die Wissenschaft hinter Dingen wie Flugzeugen, Funkgeräten und Gewehren nicht verstanden.
    Ebenso sieht ein Cargo-Cult-Entwickler zwar mögliche Ergebnisse, versteht aber nicht die First Principles und imitiert die Handlungen der Hohepriester der Technik in der Hoffnung, Erfolg kopieren zu können.
    So wird immer wieder kopiert, eingefügt, ausprobiert, herumgebastelt, gesucht, gepullt, gepusht und angepasst, in der Hoffnung, dass es diesmal wenigstens mit bestimmten Daten an einem Dienstagabend ungefähr funktioniert.

    • Ich würde das nicht als Cargo-Cult-Entwicklung sehen. Beim Cargo Cult geht es eher darum, Praktiken ohne Verständnis nachzuahmen, die nur innerhalb eines größeren Kontexts funktioniert haben, obwohl dieser Kontext verschwunden ist.
      Tatsächlich wiederholt man Handlungen oder Rituale, die an sich wirkungslos sind, und hofft auf die Ergebnisse, die ein anderes Unternehmen erzielt hat, das dieselben Rituale durchgeführt hat.
      Im ursprünglichen Artikel geht es um etwas anderes. Das, was kopiert wird, nämlich Code, hat für sich genommen eine Wirkung. Man kann ihn testen und beurteilen, ob er funktioniert.
      Diese Unterscheidung ist wichtig. Da die Symptome des Makefile-Effekts im Originalartikel und die des Cargo Cults unterschiedlich sind, erschwert es die Diagnose, wenn man beides gleichsetzt. Beim Cargo Cult verschwendet man wegen Aberglaubens Zeit mit Dingen, die tatsächlich nicht funktionieren. Beim Makefile-Effekt ist die Funktion nachgewiesen, aber während rudimentartige Überbleibsel mitkopiert werden, wird die Wartung nach und nach schwieriger.
    • Ich bin der Autor des Artikels. Das steht in Fußnote 1.
      Genauer gesagt glaube ich nicht, dass es exakt dasselbe ist wie Cargo Cult. Cargo Cult impliziert mangelndes Verständnis. Man kann ein System aber durchaus gut verstehen und trotzdem hauptsächlich so vorgehen, weil die inhärente Komplexität des Systems Copy-and-paste begünstigt. Genau das war der Kern des Artikels.
    • Oft kopiere ich Dinge, die ich früher selbst geschrieben habe. Das passiert, wenn ein Tool zu lästig ist und die Kosten für den kognitiven Kontextwechsel zu hoch sind.
      Meist verstehe ich, was intern passiert, aber schon in diesen „Modus“ zu wechseln ist kognitiv schwer, daher vermeide ich es nach Möglichkeit.
      Zu den Tools in dieser Kategorie gehören viele betriebliche Werkzeuge wie CI/CD, k8s und Docker, die enorm komplex sind, aber nicht das Kernproblem, das ich lösen will. Bei Make ist es besonders schwer, den Kontextwechsel zu vermeiden, deshalb meide ich es heutzutage einfach.
      Das hat nichts mit Zaubersprüchen zu tun; ich kenne den Trade-off, den ich eingehe. Trotzdem besteht die Gefahr, dass daraus ein Makefile-Effekt wird.
    • Der Artikel behandelt das in Fußnote 1 teilweise ebenfalls:
      „Der Makefile-Effekt ähnelt anderen Phänomenen wie Cargo Cult, Normalisierung von Abweichungen oder ‚Write-only-Sprachen‘. In diesem Artikel werde ich argumentieren, dass er sich von jedem davon etwas unterscheidet, weil er nicht per se ineffizient oder schlecht ist, sondern die Folgen eines bestimmten Designs behandelt.“
    • Mein Programmierverständnis fühlt sich eher wie „Anfänger unter Anfängern“ an. Heißt das, dass man einen strukturierten Ablauf wie Bildung → Lernen → Ausführen → Scheitern → Wiederholen braucht, um eine Cargo-Cult-Denkweise zu vermeiden?
      Bedeutet das dann, dass für jemanden, der wirklich „die Insel verlassen und ein Flugzeug fliegen“ will, letztlich die Universität der „echtesten“ Weg ist?
      Ich weiß, dass man das kaum absolut sagen kann, dass es viele Ausnahmen gibt und dass Menschen sehr unterschiedliche Rechtfertigungen à la „das kann ich nicht“ haben. Ich frage hier aus Sicht einer optimalen Theorie. Der optimale Weg, kultisches Verhalten zu vermeiden, ist, das Ganze zu verstehen – und kommt dieses „Ganze“ nicht aus der Hochschulbildung?
      Logisch betrachtet scheint es so, als würde selbst ein ernsthaftes Bücherstudium, mit dem man die „Vollständigkeit“ der Universität einholen oder übertreffen will, in mancher Hinsicht hinter der Zeit mit kundigen Lehrenden und im Unterricht zurückbleiben. Selbst wenn man annimmt, dass dieselbe Person auf beiden Wegen gleich hart arbeitet.
  • Ein weiterer Faktor ist die Nutzungshäufigkeit. Größere Texte in LaTeX schreibe ich höchstens einmal im Jahr.
    LaTeX auf dem Niveau, auf dem ich es nutze, ist kein schwieriges Werkzeug, aber wenn man es nur ein paar Wochen im Jahr verwendet, kann man sich die Details der Bedienung unmöglich merken, deshalb starte ich neue Dokumente meist, indem ich ein früheres Dokument kopiere und einfüge.

    • Relativ häufig genutzte Techniken wie Makefiles und Shell-Skripte versuche ich zu lernen, um den „Makefile-Effekt“ zu vermeiden.
      LaTeX habe ich früher sehr viel benutzt, aber trotzdem immer aus Templates kopiert und eingefügt. Bei beamer-Präsentationen und TikZ-Abbildungen war es noch schlimmer: Da habe ich eher aus früheren Präsentationen oder Abbildungen kopiert als aus Templates.
      Bei TikZ liegt es meiner Meinung nach daran, dass das Tool selbst inhärent komplex ist und ich es nicht ausreichend gelernt habe.
      LaTeX glaube ich ausreichend gelernt zu haben, also könnte es einen anderen Grund geben.
      Meiner Ansicht nach kann es ein Problem der vernünftigen Defaults sein. Ein gutes Tool sollte gute Defaults bereitstellen. Nach diesem Maßstab ist LaTeX aber kein gutes Tool. Meine Dokumente beginnen meistens ungefähr so:
      \documentclass[paper=a4, DIV9, 12pt, abstracton, headings=normal,  
      captions=tableheading]{scrartcl}  
      \usepackage[T1]{fontenc}  
      \usepackage[utf8]{inputenc}  
      \usepackage[english,german,ngerman]{babel}  
      \usepackage[english,german]{fancyref}  
      % ...  
      \usepackage{microtype}  
      \usepackage{hyperref}  
      
      Das meiste davon dient dazu, grundlegende Unterstützung für Nicht-ASCII-Zeichen in meiner Muttersprache zu bekommen oder vernünftige Defaults wie A4-Papier und microtype zu aktivieren. Bei modernen Tools wie pandoc/Markdown wäre das vielleicht nicht nötig.
      Deshalb besteht der Zweck solchen Copy-and-paste oft darin, gute Defaults zu erhalten, die ein besseres Tool von Anfang an bereitgestellt hätte.
    • Ich nutze LaTeX häufiger, beginne aber ebenfalls mit einem kopierten Header. Darin sind die für meine Sprache nötigen Pakete (fontenc, babel, lokale Schriftsatzpakete), Pakete, die ich fast immer brauche, wie graphicx/fancyhdr/hyperref/geometry, sowie in meinem Fachgebiet nützliche Definitionen für Symbole und Namen.
      Wenn man nicht ganz ohne Mathematik schreibt oder ausschließlich englischen Fließtext verfasst, ist LaTeX ziemlich „Batterien nicht enthalten“.
  • Das ist Copy-Paste-getriebene Entwicklung [0] und hat nicht nur mit Makefiles zu tun. Es geht darum, dass die gesamte Branche Code überallhin kopiert, ohne zu wissen, was sie da eigentlich kopiert.
    Ehrlich gesagt glaube ich, dass Copilot das noch verschlimmert hat, weil man Codeblöcke blind in die Codebase übernimmt.
    [0] https://andrew.grahamyooll.com/blog/copy-pasta-driven-develo...

    • Man sollte den Business-Leuten die Schuld geben. Ich habe wahrscheinlich mindestens sieben Mal hintereinander versucht, ein make-Experte zu werden, aber mir wurde nie die Zeit gegeben, mich täglich damit zu beschäftigen, bis ich es vollständig verinnerlicht hatte.
      Irgendwann habe ich einfach aufgegeben. Es wurde zu schwer zugänglichem Geheimwissen, bei dem man kein Muskelgedächtnis aufbauen kann und das man jedes Mal von Grund auf neu lernen muss, wenn man es braucht. Also bin ich auf einfachere Tools umgestiegen.
      Der Verlust von Deep Work ist nicht die Schuld guter Programmierer, sondern die der Business-Leute.
  • Ich habe viel zu oft gesehen, dass jemand ein Makefile aus einem anderen Projekt unverändert kopiert und dann so anpasst, dass es „funktioniert“, dabei aber völlig irrelevante, unnötige Build-Schritte und Targets stehen lässt.
    Mich persönlich stört das sehr.

    • Wenn es keinerlei Dokumentation gibt, woher soll man dann wissen, was relevant ist und was nicht?
      Durch Trial and Error? Na dann viel Spaß :p
  • Es stimmt, dass es viele Tools gibt, die komplexer sind als nötig, aber Make selbst halte ich nicht für ein passendes Beispiel dafür.
    Bei modernen Tools wird das Komplexitätsproblem oft durch mangelhafte Dokumentation verschärft: Cookbook-artige Dokumentation, Dokumentation, die kein konzeptionelles Modell erklärt, das man braucht, um die Funktionsweise des Tools herzuleiten, oder Dokumentation ohne ausreichend detaillierte und präzise Spezifikation.
    Bei Make ist das nicht so. Es ist gut dokumentiert und eigentlich nicht schwer zu verstehen, wenn man sich nur die Zeit nimmt, die Dokumentation zu lesen.
    Der oben genannte Cookbook-Ansatz führt zu einer Kultur, die das Lernen und Verstehen der verwendeten Tools sowie die Bedeutung gründlicher Dokumentation, die das ermöglicht, gering schätzt. Oder die Kausalität könnte auch umgekehrt sein.
    So oder so sehe ich das Problem darin, dass zu wenig Zeit darauf verwendet wird, umfassende und aktuelle Tool-Dokumentation zu erstellen, zu wenig darauf, Tools überhaupt so zu entwerfen, dass eine solche Dokumentation möglich ist, und zu wenige Ressourcen dafür bereitgestellt werden, die nötigen Tools zu lehren und zu lernen.