1 Punkte von GN⁺ 2024-03-25 | 1 Kommentare | Auf WhatsApp teilen
  • Anfang 1982 stand das Lisa-Softwareteam unter dem Druck, innerhalb von 6 Monaten zu veröffentlichen, und wollte den Fortschritt anhand der wöchentlichen Codezeilen pro Ingenieur messen
  • Bill Atkinson war der Ansicht, dass die Zeilenzahl die Produktivität nicht angemessen widerspiegelt und zudem dem Ziel widerspricht, kleine, schnelle Programme zu entwickeln
  • Als er die Bereichsberechnungs-Engine von QuickDraw mit einem einfacheren und allgemeineren Algorithmus neu schrieb, wurden Bereichsoperationen fast 6-mal schneller und der Code um etwa 2.000 Zeilen reduziert
  • Im ersten Managementformular, das nach der Zahl der in dieser Woche geschriebenen Codezeilen fragte, trug Bill -2000 ein und legte damit die Schwäche dieser Messmethode offen
  • Einige Wochen später verlangten die Manager dieses Formular von Bill nicht mehr, und die Anekdote zeigt, dass Management auf Basis von Codezeilen echte Verbesserungen übersehen kann

Messung der Codezeilen im Lisa-Team

  • Anfang 1982 wollte das Lisa-Softwareteam das Arbeitstempo erhöhen, um die Software innerhalb der nächsten 6 Monate auszuliefern
  • Einige Manager versuchten, den Fortschritt anhand der Codezeilen zu verfolgen, die jeder Ingenieur pro Woche schrieb
  • Die Ingenieure erhielten ein Formular, das sie jeden Freitag abgeben mussten; darin gab es ein Feld für die Anzahl der in dieser Woche geschriebenen Codezeilen

Bill Atkinsons -2000

  • Bill Atkinson, Autor von QuickDraw und wichtiger Designer der Benutzeroberfläche, spielte eine zentrale Rolle bei der Umsetzung von Lisa
  • Bill war der Ansicht, dass die Kennzahl der Codezeilen die Produktivität nicht angemessen misst
    • Er meinte, das Ziel guter Software sei es, möglichst kleine, schnelle Programme zu schreiben
    • Eine Kennzahl, die mehr Zeilen belohnt, kann dazu verleiten, schlampigen, aufgeblähten und fehleranfälligen Code zu schreiben
  • Damals optimierte er gerade die Bereichsberechnungs-Engine von QuickDraw
    • Er schrieb die Bereichs-Engine vollständig mit einem einfacheren und allgemeineren Algorithmus neu
    • Danach waren Bereichsoperationen fast 6-mal schneller
    • Gleichzeitig verringerte sich der Code um etwa 2.000 Zeilen
  • Als er das erste Managementformular ausfüllte, betrachtete er kurz das Feld für die Zahl der Codezeilen und schrieb dann -2000 hinein
  • Wie die Manager genau reagierten, ist nicht sicher, aber einige Wochen später musste Bill das Formular nicht mehr einreichen

1 Kommentare

 
GN⁺ 2024-03-25
Meinungen auf Hacker News
  • Das erinnert an den Konflikt um Codezeilen zwischen Microsoft und IBM
    In der PBS-TV-Serie, die auf Bob Cringelys Accidental Empires basiert, gibt es eine Szene, in der Steve Ballmer von seinen Erfahrungen bei der gemeinsamen Entwicklung von OS/2 mit IBM erzählt
    Microsoft hatte die Haltung eines kleinen Unternehmens, Dinge zu Ende zu bringen, während IBM sich auf interne Kennzahlen konzentrierte, insbesondere darauf, die Produktivität von Programmierern in KLoC (tausend Codezeilen) zu messen
    Ballmer sagte: „Alles, was sie interessierte, war KLoC, KLoC und noch mal KLoC“, und IBM schien eher auf die Menge des Codes zu schauen als darauf, ob er gut war
    https://ubiquity.acm.org/article.cfm?id=1022357

    • IBM war damit nicht allein. Vor einigen Jahren arbeitete ich an einem großen Projekt, bei dem ein großer internationaler Beratungskonzern der Hauptauftragnehmer war; als die Codebase eine Million Zeilen überschritt, wurde eine Party für das ganze Team veranstaltet
      Die Leute, die die Lage kannten, nahmen diese „Feier“ eher wie eine Beerdigung auf
    • Die hier gemeinte TV-Serie ist Triumph of the Nerds, und sie ist auch heute noch hervorragend. Vielleicht lohnt sie sich heute sogar noch mehr
  • Codezeilen als Produktivitätskennzahl zu zählen, ist wirklich töricht
    Ich habe einmal einen 20 Jahre alten, unlösbaren Bug mit einer einzigen Codezeile behoben, und ich erinnere mich, dass ein drei Jahre alter Bug mit einem einzigen order by gelöst wurde. Wie will man die Wirkung einer einzelnen Codezeile messen? Meiner Erfahrung nach schreiben schlechte Programmierer deutlich mehr Code
    Unvergesslich ist auch die Geschichte[1], dass ein Microsoft-Entwickler IBM-Code mit 33.000 Zeichen neu schrieb und auf 220 Zeichen reduzierte. Dadurch wurde Microsofts Arbeitsaufwand angeblich „negativ“, und es brach ein Krieg aus
    [1] https://archive.org/details/bigbluesunmaking00carr/page/4/mode/2up Seite 101

    • Produktivitätskennzahlen an sich sind meist töricht und ein einfacher Weg, Entwickler dazu zu bringen, Kennzahlen zu optimieren statt gute Arbeit zu leisten
      Ein heutiges Beispiel sind Unternehmen, die „Impact“, also die Einführung neuer Produkte, als Beförderungskriterium nehmen. Das führt leicht zu einer Menge gescheiterter Produkte, die niemand mehr wartet
    • Es gibt sicher Engineers, die alle paar Monate einen kritischen Bug beheben und damit Werte in Millionenhöhe schaffen, aber im Allgemeinen haben gute Engineers einen hohen Output, und Engineers mit geringem Output sind oft nicht besonders gut
    • Über längere Zeiträume betrachtet gibt es meines Erachtens eine gewisse Beziehung zwischen Codezeilen und Engineering-Output
      Unter den großen Informatikern und Engineers gibt es einige mit enormem Code-Output, und ich glaube, dass sich das auf irgendeine Weise direkt in Wirkung übersetzt. Das Problem entsteht in dem Moment, in dem Codezeilen zur Leistungskennzahl werden
      Dann greift Goodharts Gesetz: „Wenn eine Messgröße zum Ziel wird, hört sie auf, eine gute Messgröße zu sein“
    • Wie das Beispiel zeigt, ist einer der Gründe, warum Codezeilen eine schlechte Produktivitätskennzahl sind, dass sie ziemlich gut die Last abbilden, die den Wartenden einer Codebase aufgebürdet wird
      Aus Sicht von Produktivitätskennzahlen wird Code als Asset eingestuft, aber näher an der Realität ist die Sichtweise, dass Features die Assets sind und der Code selbst eine Verbindlichkeit
  • Dieses Thema taucht häufig auf. Frühere Diskussionen sind unter anderem:
    https://news.ycombinator.com/item?id=33483165 (2022)
    https://news.ycombinator.com/item?id=26387179 (2021)
    https://news.ycombinator.com/item?id=10734815 (2015)
    https://news.ycombinator.com/item?id=7516671 (2014)
    https://news.ycombinator.com/item?id=4040082 (2012)
    https://news.ycombinator.com/item?id=1114223 (2010)
    https://news.ycombinator.com/item?id=1545452 (2010)

  • Zu Beginn meiner Karriere habe ich einmal ein geerbtes C-Programm mit über 10.000 Zeilen auf weniger als 500 Zeilen optimiert. Es war ein C-Programm, das SQL-Aufrufe an eine Sybase-Datenbank machte
    Das lag nicht an einer großartigen Einsicht, sondern an der einfachen Annahme, dass der Vorgänger womöglich nicht wusste, wie man Funktionen verwendet oder wie man Parameter nutzt, um variable Daten in SQL-Abfragen einzusetzen. Tatsächlich hatte er dieselbe SQL-Anweisung immer wieder inline geschrieben und nur ein paar Werte geändert
    Ich schrieb den Code für die SQL-Aufrufe als Funktionsaufrufe neu und übergab die Bind-Variablen als Funktionsparameter. Der wiederholte Inline-Code wurde durch einen Funktionsaufruf in einer Schleife ersetzt, der die wechselnden Bind-Werte aus einem Array entnahm

  • Die größte Wirkung entsteht manchmal dadurch, dass man eine einfache Frage stellt wie „Wie wollt ihr X behandeln?“ und so dafür sorgt, dass etwas gar nicht erst gebaut wird.
    Wenn dieses Etwas nie die Chance gehabt hätte, richtig zu funktionieren, hat man sich die gesamten Kosten des Versuchs gespart, es zu bauen.
    So etwas lässt sich nicht nur unmöglich in Zahlen messen, es schafft einem auch Feinde. Trotzdem Applaus für alle, die es wagen, das zu tun.

    • Deshalb bringe ich Neuen bei, so eine Schleife im Kopf zu haben und nicht sofort schnell auf die Tastatur einzuhämmern.
      Leute, die Programmieren mit schnellem Tippen verwechseln, zeigen interessante Parallelen zu LLMs: schlecht geschriebenen Code komplett hinschreiben, löschen, wieder hinschreiben, wieder löschen.
    • Als ich in einem Großunternehmen Software verwaltete, hatte ich eine Bleistiftbox auf dem Schreibtisch.
      Etwa die Hälfte der Informationsanfragen, die in die Abteilung kamen, lautete immer sinngemäß: „sehr wichtig, sofort benötigt, kann viel Geld einbringen oder sparen“. Die offensichtliche Antwort war aber: „Rechnen Sie es mit den Informationen aus, die Sie bereits haben. Sie haben doch Taschenrechner und Tabellenkalkulation. Soll ich Ihnen einen Bleistift geben?“
      Es ist besser, zu vermeiden, dass ein System X verarbeiten muss, als es dazu zu bringen. Spezialfälle, die vielleicht ein- oder zweimal genutzt werden, blähen das System auf, und niemand weiß, dass es diese Spezialfälle oder Programme gibt oder was sie tatsächlich tun. Selbst wenn sie gut dokumentiert sind, nimmt sich niemand die Zeit zu lernen, was möglich ist. Daher sind die meisten solcher Spezialfunktionen in der Praxis Zeitverschwendung.
  • Als entsprechendes Gedankenexperiment kann man sich die Gegenposition vorstellen. Wenn ein Manager diesen Artikel liest und beschließt, schlicht nach der Zahl gelöschter Codezeilen zu messen: Würde es besser oder schlechter?

    • Je nach Unternehmen und Messmethode ließe sich das leichter manipulieren. Man lässt llama plausibel wirkenden Code erzeugen, fügt ein wenig Code hinzu, sodass er in der Praxis keinen Effekt hat, committet das und löscht ihn später wieder.
      Solche Messgrößen sind im Allgemeinen nahezu nutzlos, solange es keine robusten Code-Review-Praktiken gibt. Entgegen dem, was die Leute hier gern glauben möchten, sind solche Praktiken selten. Wenn es aber gute Reviews gibt, fallen Minderleistung oder KPI-Gaming ohnehin auf, sodass es weniger Grund gibt, solche Metriken überhaupt einzuführen.
    • Es wäre etwas schlechter, aber vielleicht nicht so schlimm, wie man denkt. Denn in der Branche gibt es bereits ähnliche kurzsichtige Impulse in diese Richtung.
      Zum Beispiel die alte Idee, Software Engineers und schwer verständlichen Code-Text ganz abzuschaffen und sie dadurch zu ersetzen, dass Produktmanager spezielle Diagramme oder Flussdiagramme zeichnen, aus denen dann „Low-Code“- oder „No-Code“-Ergebnisse entstehen.
    • Allen zeilenbasierten Metriken sollte man misstrauen, aber ΔSLOC ist vermutlich eine der weniger schlechten.
      Wenn man hinzugefügte und gelöschte Zeilen getrennt zählt, würde ein Patch mit +50,-150 als 200 ΔSLOC zählen.
      Das ist kein gutes Maß für Produktivität, schon gar nicht für sich allein. Als grobe Überschlagsmetrik für das Änderungsvolumen ist es aber vernünftig. Ob ein Entwickler mit hohem ΔSLOC produktiver ist als ein Kollege, der ein bis zwei Wochen lang gar kein ΔSLOC hat, hängt davon ab, was dieser Kollege tut; sicher ist jedoch, dass Ersterer im Messzeitraum die Codebasis stärker verändert.
    • Es wird schlechter. Es ist nicht wünschenswert, die gesamte Codebasis zum Ziel von Code Golf zu machen.
    • Neue Funktionen wird es dann mit Sicherheit nicht geben.
      Wenn das Produkt „fertig“ ist, könnte es gleich gut oder besser sein. Wenn nicht, werden Änderungen mit negativer Zeilenzahl es nicht bis ins Deployment schaffen.
      Die meisten Produkte entwickeln sich jedoch ständig weiter. Genau deshalb können wir jahrelang am selben Projekt bleiben, und Beiträge, die nur löschen, fügen am Ende nichts hinzu.
  • Die eigentliche Geschichte ist, dass man beim Start eines Projekts manchmal nicht genau weiß, wohin es gehen soll.
    Im Verlauf versteht man das Problem und die gewünschte Antwort viel besser, und dann kann man große Blöcke herausreißen und durch kleinere, bessere ersetzen.
    Außerdem darf man nicht vergessen, dass diese Leute -2000 Codezeilen, darunter sogar Assembly-Code, entfernen mussten, um alles in ein 64-KB-ROM zu bekommen. Der Druck, es kleiner zu machen, war sehr groß.

  • Das ist Bill Atkinson, bekannt durch Atkinson Dithering. https://beyondloom.com/blog/dither.html

    • Bill Atkinson entwickelte QuickDraw, die Grafikbibliothek, die die Grundlage der Lisa- und Mac-UI bildete, außerdem MacPaint und HyperCard.
      Dabei musste er ständig neue Arten erfinden, wie Benutzeroberflächen funktionieren, und wie man Software schreibt, um diese Probleme zu lösen. Er optimierte gleichzeitig darauf, „auf der Mac-Hardware schnell lauffähig“ zu sein und „eine hervorragende User Experience zu bieten“, und diese Synergie hinterließ seine Spuren in der gesamten Ästhetik der alten Schwarz-Weiß-Macs. Auch dieser Dithering-Stil ist ein weiteres Beispiel für die Verbindung von algorithmischer Genialität und ästhetischem Gespür.
      Dieses Gespür zeigt sich auch in Dingen wie der Auswahlumrandung „marching ants“ (https://en.wikipedia.org/wiki/Marching_ants). Ähnlich war es damit, dass viel Feedback in der klassischen Mac-UI durch Pixel-Invertierung ausgedrückt wurde: Textauswahl, Menü-Hervorhebungen, die Darstellung eines Buttons während gedrückter Maustaste, die Umrisslinie beim Ziehen eines Fensters usw. Das Zeichnen darüber im XOR-Modus war eine sehr gute Methode, um solche Effekte zu erzeugen.
      Die Art, wie diese Werkzeuge in QuickDraw kombiniert wurden, führte dazu, dass der berühmte Dialog mit Steve Jobs über abgerundete Rechtecke (https://www.folklore.org/Round_Rects_Are_Everywhere.html) tatsächlich darin mündete, dass man in QuickDraw abgerundete Rechtecke genauso einfach zeichnen konnte wie normale Rechtecke, wodurch abgerundete Rechtecke überall im Betriebssystem auftauchten.
      Der Erfolg der Mac-UI lag nicht nur daran, dass sie gut aussah. Zu einem großen Teil lag er daran, dass Bill Atkinson ein cleveres, kleines Toolset schuf, mit dem man gut aussehende Dinge leicht bauen konnte.
      Auch Susan Kares hervorragende Icons wären wohl nicht so liebevoll in Erinnerung geblieben, wenn Bill keine Werkzeuge geschaffen hätte, mit denen sich 32x32-Pixel-Masken-Bitmaps leicht in die UI einfügen und beim Anklicken invertieren ließen.
  • Die Lehre ist: Selbst wenn man so klug ist wie Einstein, ist man am Ende Angestellter und muss tun, was man als Angestellter zu tun hat.

    • Wenn Einstein unter Kennzahlendruck gestanden hätte, hätten wir seinen Namen wohl nie gehört.
  • Ich habe nie verstanden, warum Leute, wenn sie über geschriebene Codezeilen sprechen, immer „hinzugefügte Zeilen minus gelöschte Zeilen“ rechnen.
    Nur weil ich 10 km laufe und zum Startpunkt zurückkehre, heißt das nicht, dass ich 0 km gelaufen bin.

    • Das liegt wohl teilweise auch daran, dass dumme Diff-Tools selbst dann große Unterschiede ausweisen können, wenn sich funktional nur wenig ändert, aber Zeilen hin- und hergeschoben wurden.
      Zum Beispiel wenn man eine Form wie if cond { ... return; } ... in if cond { ... return; } else { .... } ändert.
      Trotzdem deckt diese Erklärung nicht alles ab.