5 Berühmte Programmierzitate, erklärt
Programmierer zu sein bedeutet, sich für ein Leben des ständigen Lernens anzumelden. Die Quelle des Neuen — neue Funktionen, neue Sprachen, neue Tools, neue Frameworks – hört nie auf zu sprudeln. Die Informatik ist aber auch ein überraschend traditionelles Gebiet, das auf bewährten Prinzipien beruht. Wir haben objektorientierte Programmierung, moderne Hardware und künstliche Intelligenz hinzugefügt. Aber trotz dieser Veränderungen, Viele der Erkenntnisse, die vor einer Generation zum ersten Mal artikuliert wurden, gelten auch heute noch.
In diesem Artikel habe ich einige meiner Lieblingszitate über Informatik seziert. Die einzige Bedingung, die ich stelle, ist, dass jedes Zitat mindestens zwanzig Jahre alt sein muss. Denn während alte Technik schnell unbrauchbar wird, haben die alten Gebote unserer Programmiervorfahren viel mehr Durchhaltevermögen.
” Alle Probleme in der Informatik können durch eine andere Indirektionsebene gelöst werden.” – David Wheeler
Hier ist ein oft wiederholtes compsci-Zitat, das nur wenige Entwickler erklären möchten. Aber es ist eine meiner Lieblingsprogrammwahrheiten, weil es den Kern dessen trifft, worum es beim Programmieren geht.
Der einfachste Weg, über Indirektion nachzudenken, besteht darin, sich Ebenen vorzustellen. Angenommen, Sie haben ein kleines Projekt, das Komponente A in Komponente B einfügen muss:
Beide Komponenten sind standardisiert, sodass Sie sie nicht aufbrechen und ihre Funktionsweise ändern können. Sie könnten eine ganz neue Komponente erstellen (PlugTwoProngVariant
), aber das ist viel Arbeit und unnötige Duplizierung. Ein besserer Ansatz besteht darin, eine Ebene zwischen den beiden Teilen hinzuzufügen — einen Adapter, der in beide Komponenten passt und zwischen ihnen übersetzt wird.
Wenn es bei der Indirektion nur darum ginge, eine neue Ebene hinzuzufügen, um inkompatible Teile zusammenzupassen, wäre dies schön, aber nur begrenzt nützlich. Aber die Idee, Probleme zu lösen, indem man um sie herum baut, ist ein Konzept, das sich von unten nach oben erstreckt. Sie sehen es, wenn Sie versuchen, ein neues Datenmodell an eine alte Benutzeroberfläche anzupassen. Sie sehen es, wenn Sie versuchen, eine Legacy-Anwendung an ein neues Webdienst-Backend anzupassen. Sie sehen es, wenn Sie Funktionen auf höherer Ebene wie Protokollierung und Caching aktivieren oder Dienste auf höherer Ebene wie Messaging und Transaktionen koordinieren müssen. Und an der Spitze der Pyramide kommen Sie zu verdünnten Themen wie maschinellem Lernen (wenn Sie das gewünschte Verhalten nicht codieren können, schreiben Sie eine weitere Codeebene, die es für Sie herausfindet).
Viele Leute werden dir sagen, dass es beim Programmieren darum geht, explizite Anweisungen in einer Sprache zu schreiben, die selbst idiotische Computer verstehen können. Aber David Wheelers Zitat offenbart eine bessere Einsicht. Bei guter Programmierung geht es darum, die Leiter der Abstraktion zu erklimmen, um zu den allgemeinsten Lösungen zu gelangen.
Bonusbezogenes Zitat:
Indirektion ist mächtig, aber Komplexität kostet. Die Leute zitieren sehr selten Wheelers unmittelbare Folgebemerkung über Indirektion:
” Aber das wird normalerweise ein anderes Problem schaffen.” – David Wheeler
Diese Wahrheit hat Programmierer seitdem im Geschäft gehalten.
Über Einfachheit
” Einfachheit ist Voraussetzung für Zuverlässigkeit.” – Edsger Dijkstra
Es gibt keinen Mangel an weisen Programmierern, die uns warnen, unseren Code nicht zu kompliziert zu machen. Aber nur wenige stellen die Kosten der Komplexität klarer dar als der niederländische Informatikpionier Edsger Dijkstra.
Hier ist die Einsicht: Du wählst Einfachheit nicht als Geschenk an die Zukunft. Sie tun dies nicht, weil Sie die Möglichkeit erwarten, Ihren Code wiederzuverwenden, oder weil Sie möchten, dass er bei einer Codeüberprüfung sauberer aussieht, oder weil Sie die Änderung vereinfachen möchten. (Obwohl all diese Vorteile wertvoll sind!) Sie tun es, weil Einfachheit eine Voraussetzung ist. Ohne Einfachheit können Sie niemals zuverlässigen Code haben, dem Sie vertrauen können, um ein Unternehmen zu führen oder Ihre Daten zu verwalten.
Um Dijkstras Standpunkt zu akzeptieren, müssen wir neu definieren, was “guter Code” bedeutet. Es ist nicht der kürzeste Code. Es ist nicht unbedingt der schnellste Code. Es ist definitiv nicht der klügste Code. Es ist Code, dem man vertrauen kann.
Bonusbezogenes Zitat:
Eine der besten Möglichkeiten, Code einfach zu halten, besteht darin, sich daran zu erinnern, dass weniger mehr ist. Dijkstra bietet eine Metrik, die uns dabei hilft, dies zu berücksichtigen:
” Wenn wir Codezeilen zählen wollen, sollten wir sie nicht als ‘produzierte Zeilen’ betrachten, sondern als ‘ausgegebene Zeilen’.’ “- Edsger Dijkstra
Über Lesbarkeit und Umschreibungen
” Es ist schwieriger, Code zu lesen, als ihn zu schreiben.” – Joel Spolsky
Auf den ersten Blick scheint dieses Zitat der Software-Legende und StackOverflow-Mitschöpfer Joel Spolsky wahr, aber täuschend flach. Ja, Code kann dicht, knapp und langwierig sein. Und es ist nicht nur der Code anderer Leute. Wenn Sie sich Ihre eigene Arbeit von vor einem Jahr ansehen, werden Sie wahrscheinlich etwas Zeit brauchen, um die Logik zu sortieren, die Sie einst genau kannten.
Aber Spolskys Einsicht hat eine Wendung. Die Gefahr von Code, den Sie nicht lesen können, ist nicht nur offensichtlich (es ist schwer, ihn zu ändern und zu verbessern). Stattdessen besteht die größere Gefahr darin, dass komplexer Code schlechter zu sein scheint, als er tatsächlich ist. Tatsächlich ist die Last, den bereits geschriebenen Code eines anderen zu verstehen, so groß, dass Sie versucht sein könnten, das zu machen, was Spolsky als den schlimmsten Fehler bezeichnet — die Entscheidung, diesen Code von Grund auf neu zu schreiben.
Es ist nicht so, dass Umschreibungen die Architektur eines Systems nicht verbessern können. Sie können es definitiv. Diese Verbesserungen sind jedoch mit hohen Kosten verbunden. Sie setzen die Uhr beim Testen und Beheben von Fehlern zurück, zwei Aktivitäten, die viel länger dauern als das bloße Codieren. Umschreibungen sind verlockend, weil sie mit einer der häufigsten Vorurteile in der Softwareentwicklung spielen: Wir unterschätzen den Aufwand, Dinge zu tun, die konzeptionell einfach sind. Das ist der Grund, warum die letzten 5% eines Projekts 50% der Zeit in Anspruch nehmen. Einfache Dinge können überraschend zeitaufwendig sein! Und nichts scheint einfacher zu sein, als ein Problem zu lösen, das Sie bereits gelöst haben.
Wenn Sie also nicht alles neu schreiben sollten, um es perfekt zu machen, was ist die bessere Lösung? Die Antwort ist, jeden Entwickler in ständiges mundgerechtes Refactoring einzubeziehen. Dadurch erhalten Sie kleine, kontinuierliche Codeverbesserungen – echte Belohnungen mit minimalen Risiken. Sie können die Lesbarkeit unterwegs verbessern.
Bonus Verwandtes Zitat:
Wenn Sie immer noch Zweifel an der Wichtigkeit der Lesbarkeit haben, hilft Martin Fowler, es in die richtige Perspektive zu rücken:
” Jeder Narr kann Code schreiben, den ein Computer verstehen kann. Gute Programmierer schreiben Code, den Menschen verstehen können.” – Martin Fowler
Mit anderen Worten, die Aufgabe eines Programmierers besteht nicht nur darin, die Dinge zum Laufen zu bringen, sondern die Dinge sinnvoll zu gestalten.
Auf Wiederholung
” Wiederhole dich nicht. Jedes Wissen muss eine einzige, eindeutige und maßgebliche Repräsentation innerhalb eines Systems haben.” – Andy Hunt und Dave Thomas
Jeder Programmierer mit Selbstachtung weiß, dass Wiederholung das Herz von viel Bösem ist. Wenn Sie dasselbe an verschiedenen Orten schreiben, machen Sie zusätzliche Arbeit beim Schreiben, Testen und Debuggen. Schlimmer noch, Sie führen die Möglichkeit von Inkonsistenzen ein — zum Beispiel, wenn ein Teil des Codes aktualisiert wird, aber andere, ähnliche Routinen nicht in Übereinstimmung gebracht werden. Ein inkonsistentes Programm ist ein Programm, dem Sie nicht vertrauen können, und ein Programm, dem Sie nicht vertrauen können, ist keine praktikable Lösung mehr.
Code ist jedoch nicht der einzige Ort, an dem Wiederholung Chaos anrichtet. Diese Version der berühmten “Don’t repeat yourself” (DRY) -Regel erweitert das Prinzip der Nicht-Duplikation, um die anderen Stellen abzudecken, an denen sich Inkonsistenzen verbergen können. Wir sprechen nicht mehr über Code-Duplizierung. Wir sprechen auch von Wiederholung in einem System — und ein System hat viele verschiedene Möglichkeiten, Wissen zu kodieren. Dazu gehören:
- Code-Anweisungen
- Code-Kommentare
- Entwickler- oder Client-Dokumentation
- Datenschemata (z. B. Datenbanktabellen)
- Andere Spezifikationen, wie Testpläne, Workflow-Dokumente und Build-Regeln
Alle diese Ebenen können sich überlappen. Und wenn sie es tun, riskieren sie, verschiedene Versionen derselben Realität einzuführen. Was passiert beispielsweise, wenn die Dokumentation eine Arbeitsweise beschreibt, die Anwendung jedoch einer anderen folgt? Wer hat das Eigentum an der Wahrheit? Was passiert, wenn die Datenbanktabellen nicht mit dem Datenmodell im Code übereinstimmen? Oder beschreiben die Kommentare die Funktionsweise eines Algorithmus, der nicht mit seiner tatsächlichen Implementierung übereinstimmt? Jedes System braucht eine einzige, autoritative Repräsentation, von der alles andere abgeleitet ist.
Konkurrierende Versionen der Wahrheit sind übrigens nicht nur in kleinen Projekten oder schlecht gestaltetem Code ein Problem. Eines der besten Beispiele brach mit dem Kampf zwischen XHTML und HTML5 in die Öffentlichkeit aus. Ein Lager argumentierte, dass die Spezifikation die offizielle Wahrheit sei und Browser korrigiert werden müssten, um ihr zu folgen. Die andere Fraktion behauptete, dass das Browserverhalten der De-facto-Standard sei, denn das hatten Designer im Sinn, als sie Webseiten schrieben. Am Ende gewann die Browserversion der Wahrheit. Von diesem Zeitpunkt an war HTML5 das, was Browser taten — einschließlich der Verknüpfungen, die sie erlaubten, und der Fehler, die sie akzeptierten.
Bonusbezogenes Angebot:
Die Möglichkeit, dass Code und Kommentare einander widersprechen, hat eine hitzige Debatte darüber ausgelöst, ob Kommentare mehr schaden als nützen. Die Befürworter der extremen Programmierung behandeln sie mit offenem Misstrauen:
” Code lügt nie; Kommentare tun es manchmal.” – Ron Jeffries
Über harte Probleme
” In der Informatik gibt es nur zwei schwierige Dinge: Cache-Invalidierung und Benennung von Dingen.” – Phil Karlton
Auf den ersten Blick scheint dieses Zitat ein amüsanter, aber gewöhnlicher Programmierwitz zu sein. Der Kontrast zwischen etwas, das schwierig klingt (Cache-Invalidierung) und etwas, das schmerzlos klingt (Dinge benennen), ist sofort nachvollziehbar. Jeder Programmierer hat Stunden Arbeit investiert, um ein lächerlich triviales Problem zu beheben, wie ein Parameterpaar, das in der falschen Reihenfolge übergeben wurde, oder eine inkonsistent großgeschriebene Variable (danke JavaScript). Solange Menschen mit Maschinen zusammenarbeiten müssen, um Dinge zu erledigen, wird die Programmierung ein Mashup aus Systemplanung auf hoher Ebene und trivialen Tippfehlern sein.
Aber wenn Sie sich das Zitat von Phil Karlton noch einmal ansehen, gibt es noch mehr zu entpacken. Dinge zu benennen ist nicht schwer, nur weil das Leben eines Programmierers regelmäßig durch winzige Kopfschmerzen ruiniert wird. Es ist auch, weil die Frage der Namensgebung ist eigentlich der Rand eines jeden Programmierers wichtigste Aufgabe: Software-Design. Mit anderen Worten, wie schreibt man Code, der klar, sauber und konsistent ist?
Es gibt viele Möglichkeiten, die Benennung falsch zu machen. Wir haben alle Variablen gesehen, die nach Datentypen benannt sind (myString
, obj
), abkürzungen (pc
für Produktkatalog), einige triviale Implementierungsdetails (swappable_name
, formUserInput
), oder gar nichts (ret_value
, tempArray
). Es ist leicht, in die Falle zu tappen, eine Variable basierend darauf zu benennen, was Sie gerade damit machen, und nicht, was sie enthält. Und boolesche Werte sind besonders schwierig – wird progress
gesetzt, wenn der Fortschritt beginnt, zeigen Sie an, dass Sie Fortschrittsinformationen in der Benutzeroberfläche anzeigen müssen, oder markieren Sie etwas völlig anderes?
Aber Variablennamen sind nur der Anfang. Das Benennen von Klassen wirft die Frage auf, wie Sie Code in unabhängige Teile aufteilen. Die Benennung öffentlicher Mitglieder bestimmt, wie Sie die Schnittstelle präsentieren, die es einem Teil Ihrer Anwendung ermöglicht, mit einem anderen zu interagieren. Das Sperren dieser Namen beschreibt nicht nur, was ein Code tun kann, sondern bestimmt auch, was er tun wird.
Bonusbezogenes Angebot:
” In der Informatik gibt es zwei schwierige Dinge: Cache-Invalidierung, Benennung von Dingen und Eins-zu-Eins-Fehler.” – Leon Bambrick