Schlechter Code kann funktionieren. Aber wenn der Code nicht sauber ist, kann er ein Softwareentwicklungsunternehmen in die Knie zwingen. Überall auf der Welt gehen hervorragende Ressourcen im Namen von schlecht entworfenem Code verloren. Aber das muss nicht so sein. Im August 2008 stellte der renommierte Softwareexperte Robert C. Martin ein umfassendes Buch mit dem Titel Clean Code vor. Das Buch vermittelt Ihnen die Grundwerte eines Software-Handwerkers und Ansätze, um sauberen Code zu entwerfen und Sie zu einem besseren Programmierer zu machen.
WIE DIESES BUCH UNS GEHOLFEN HAT?
Dieses Buch hat uns geholfen zu verstehen, dass wir bessere Software-Handwerker werden und sauberen Code schreiben müssen, um uns als Profis zu betrachten. Sauberer Code wirft ein Licht auf Unit-Tests, Formatierung, Debugging und die Verwendung von beschreibenden Namen, die uns helfen, saubereren und robusteren Code für unsere Kunden zu schreiben. Das Schreiben von sauberem Code ist eine Frage der persönlichen Gewohnheit und viel mehr eine Fähigkeit. Mit der Zeit müssen Sie durch Erfahrung und Wissen wachsen, um sauberen Code zu schreiben.
DAS BUCH ERKLÄRT IN 60 SEKUNDEN
Der Autor betont, dass Funktionen klein sein, eine Aufgabe erfüllen und beschreibende Namen haben sollten. Wenn eine Funktion viele Konfigurationsargumente benötigt, sollten Sie diese in eine einzige Variable für die Konfigurationsoptionen integrieren.
Das Buch betont, dass sich Entwickler an das Single Responsibility Principle halten sollen, das besagt, dass eine Klasse oder ein Modul nur einen Grund für eine Änderung haben muss. Dieses Prinzip gab uns eine Definition von Verantwortung und Richtlinien für die Klassengröße. Klassen müssen eine Verantwortung und einen Grund für eine Änderung haben.
DIE DREI BESTEN ZITATE
„Code ohne Tests ist nicht sauber. Egal wie elegant er ist, wie lesbar und zugänglich, er ist unsauber, wenn er keine Tests hat.“
„Jedes System basiert auf einer domänenspezifischen Sprache, die von den Programmierern entwickelt wurde, um dieses System zu beschreiben. Funktionen sind die Verben dieser Sprache, und Klassen sind die Substantive.“
„Fehlerbehandlung ist wichtig, aber wenn sie die Logik verdunkelt, ist sie falsch.“
BUCHZUSAMMENFASSUNGEN UND NOTIZEN
Kapitel eins: Sauberer Code
Sauberer Code ist wichtig: Falscher Code bringt ein Unternehmen irgendwann zu Fall, denn mit zunehmender Entwicklung geht die Produktivität immer mehr gegen Null.
Die Gesamtkosten für ein Chaos steigen mit der Zeit. Je unordentlicher der Code wird, desto geringer sind die Chancen, ihn zu bereinigen. Die Produktivität des Teams sinkt, je größer das Chaos wird, weil es unter Druck steht, eine Frist einzuhalten oder die Produktivität zu steigern.
Es kostet Zeit und Ressourcen, ein System von Grund auf neu zu erstellen. Refactoring und schrittweise Verbesserungen sind in der Regel die bessere Wahl. Ihren Code sauber zu halten ist kosteneffizient und eine Frage des beruflichen Überlebens.
Sie würden Monate damit verbringen, eine Aufgabe zu erledigen, für die Sie mit unordentlichem Code nur Stunden gebraucht hätten. Guter Code verrottet schnell zu falschem Code, weil sich die Anforderungen in Ansätzen ändern, die das ursprüngliche Design durchkreuzen.
Sauberer Code ist gut getestet und führt eine Aufgabe effektiv aus, während lausiger Code meist fahrlässig zu viel macht.
Unordentliche Codes bremsen Entwickler aus, aber alle fühlen sich unter Druck gesetzt, ein Chaos zu schaffen, um Termine einzuhalten. In der Regel werden Sie die Frist nicht einhalten, wenn Sie Unordnung machen. Die einzige Möglichkeit, die Frist einzuhalten, ist die Pflege eines sauberen Codes.
Lieblingszitat des Kapitels: „Sauberen Code zu schreiben, ist das, was Sie tun müssen, um sich als Profi zu bezeichnen. Es gibt keine vernünftige Entschuldigung dafür, dass Sie weniger als Ihr Bestes geben.“
Kapitel zwei: Bedeutungsvolle Namen
Es ist müßig zu kommentieren, dass Namen ihren Zweck offenbaren sollten. Die Auswahl guter Namen kostet Zeit, spart aber mehr als sie kostet. Achten Sie auf die von Ihnen gewählten Namen und ändern Sie sie, wenn Sie bessere finden.
Die Wahl eines guten Namens ist komplex, und der Name einer Funktion oder Variable sollte erklären, was sie ist, wie sie verwendet wird und warum sie existiert. Wenn ein Name einen Kommentar erfordert, verrät er nicht seine Absicht.
Sie müssen vermeiden, falsche Hinweise zu hinterlassen, die die Bedeutung des Codes verschleiern. Vermeiden Sie Wörter, deren etablierte Bedeutungen von der von Ihnen beabsichtigten Bedeutung abweichen.
Vermeiden Sie die Verwendung von Abkürzungen in Funktionsnamen und einstelligen Variablennamen, außer bei häufig verwendeten Namen wie „i“ für die Zählervariable in einer Schleife.
Variablen sollten aussprechbar sein, damit Sie über sie sprechen und sie laut aussprechen können. Sie können sie nur mit Ihren Teamkollegen besprechen, wenn Sie sie aussprechen können.
Einbuchstabige Namen und numerische Konstanten haben ein besonderes Problem. Es ist mühsam, sie in einem Textkörper zu finden. Namen mit nur einem Buchstaben können nur als lokale Variablen innerhalb kurzer Methoden verwendet werden.
Lieblingszitat des Kapitels: „Ein langer beschreibender Name ist besser als ein langer beschreibender Kommentar.“
Kapitel drei: Funktionen
Die erste Regel für Funktionen lautet: Sie müssen unbedeutend sein, und die zweite Regel lautet: Sie sollten nur eine Aufgabe ausführen. Funktionen sollten so unbedeutend sein, dass sie verschachtelte Strukturen enthalten. Daher darf die Einrückungsebene einer Funktion nicht größer als eins oder zwei sein. Das macht die Funktionen leichter lesbar und verständlich.
Funktionen sollten so wenige Parameter wie möglich haben. Parameter neigen dazu, Funktionen schwer verständlich zu machen und befinden sich auf einer niedrigeren Abstraktionsebene. Vermeiden Sie die Verwendung von Parametern so gut es geht, indem Sie abstrakte Hilfsklassen einführen oder Argumente in Mitgliedsvariablen umwandeln.
Um sicherzustellen, dass Ihre Funktionen eine Aufgabe erfüllen, müssen Sie dafür sorgen, dass die Anweisungen innerhalb Ihrer Funktionen alle auf der gleichen Abstraktionsebene liegen.
Verwenden Sie aussagekräftige Namen zur Kennzeichnung Ihrer Funktionen. Beschreibende Namen erklären, was eine Funktion tut. Je kleiner und konzentrierter eine Funktion ist, desto einfacher ist es, einen beschreibenden Namen zu wählen.
Lieblingszitat des Kapitels: „Sie wissen, dass Sie an sauberem Code arbeiten, wenn sich jede Routine als so ziemlich das herausstellt, was Sie erwartet haben.“
Viertes Kapitel: Kommentare
Die tatsächliche Verwendung von Kommentaren entschädigt Sie für Ihr Versagen, sich in Code auszudrücken. Kommentare sind durchweg Fehlschläge. Sie sollten sie haben, weil Sie nur manchmal herausfinden, wie Sie sich ohne sie beschreiben können.
Sauberer und aussagekräftiger Code mit wenigen Kommentaren ist viel besser als unordentlicher und komplexer Code mit vielen Kommentaren. Verbringen Sie daher lieber Zeit damit, das Chaos in Ihrem Code zu beseitigen, als Kommentare zu schreiben, die Ihr Chaos erklären.
Die meisten Kommentare sind Krücken und Rechtfertigungen für schlechten Code. Kommentare lassen sich vermeiden, wenn Sie eindeutig benannte Variablen verwenden und Codeabschnitte in klar benannte Funktionen einteilen.
Verwenden Sie Javadocs nicht einfach nur, um sie zu verwenden. Kommentare, die erklären, was eine Methode tut, welche Argumente sie annimmt und was sie zurückgibt, sind im besten Fall überflüssig und im schlimmsten Fall irreführend.
Kommentare müssen alle zutreffenden Informationen und den Kontext enthalten, den jemand, der die Kommentare liest, benötigt. Seien Sie nicht faul, wenn Sie Kommentare schreiben.
Lieblingszitat des Kapitels: „Kommentieren Sie keinen schlechten Code – schreiben Sie ihn um.“
Kapitel Fünf: Formatieren
Sorgen Sie dafür, dass Ihr Code ansprechend formatiert ist. Wählen Sie eine bestimmte Anzahl von überschaubaren Regeln, die das Format Ihres Codes steuern. Setzen Sie diese Regeln dann konsequent in Ihrem Code um. Noch besser ist es, wenn Sie ein Tool haben, das diese Formatierungsregeln umsetzt.
Die Formatierung von Code ist unerlässlich. Sie ist zu wichtig, um ignoriert zu werden. Verlassen Sie sich nicht darauf, dass Menschen jeden Formatierungsfehler manuell erkennen und korrigieren. Verwenden Sie stattdessen einen automatischen Code-Formatierer und Code-Linter. Das ist effizient und produktiv und spart Zeit bei der Überprüfung des Codes.
Quelldateien sollten wie ein Zeitungsartikel sein. Der Name muss einfach, aber aussagekräftig sein. Der Name sollte ausreichen, um zu erkennen, ob Sie sich in einem geeigneten Modul befinden. Die obersten Teile Ihrer Quelldatei sollten Konzepte und Algorithmen auf hoher Ebene enthalten. Dann sollten die Details nach unten hin zunehmen.
Variablen müssen in der Nähe der Stelle deklariert werden, an der sie verwendet werden. Bei kleinen Funktionen steht dies normalerweise am Anfang der Funktion. Selbst bei kurzen Funktionen sollten Sie sie gut formatieren, anstatt sie in einer einzigen Zeile zu schreiben.
Lieblingszitat des Kapitels: „Die Formatierung von Codes ist wichtig. Sie ist zu wichtig, um sie zu ignorieren, und sie ist zu wichtig, um sie religiös zu behandeln. Bei der Codeformatierung geht es um Kommunikation, und Kommunikation ist die erste Aufgabe eines professionellen Entwicklers.“
Kapitel sechs: Objekte und Datenstrukturen
Sie halten Ihre Variablen privat, weil Sie nicht wollen, dass jemand anderes von ihnen abhängt. Sie möchten die Freiheit behalten, ihren Typ oder ihre Implementierung spontan zu ändern. Viele Entwickler fügen automatisch Getter und Setter zu ihren Objekten hinzu und geben damit ihre privaten Variablen preis, als wären sie öffentlich.
Fügen Sie nicht standardmäßig Getter und Setter hinzu, sondern bieten Sie eine abstrakte Schnittstelle zu den Daten an, so dass Sie die Implementierung anpassen können, ohne an die Clients denken zu müssen.
Objekte verbergen ihre Daten hinter Abstraktionen und offenbaren Funktionen, die mit diesen Daten arbeiten, außer Sichtweite. Datenstrukturen legen ihre Daten offen und haben keine sinnvollen Funktionen.
Das Gesetz von Demeter besagt, dass ein Modul nichts über das Innere des Objekts wissen sollte, das es manipuliert. Das bedeutet, dass ein Objekt seine interne Struktur nicht durch Accessoren offenbaren sollte, denn das würde bedeuten, dass es seine interne Struktur preisgibt, anstatt sie zu verbergen. Da Objekte Daten verbergen und ihr Verhalten offenlegen, ist es mühelos möglich, neue Objekte hinzuzufügen, ohne das aktuelle Verhalten zu ändern. Datenstrukturen legen Daten offen und haben kein ungewöhnliches Verhalten, so dass das Hinzufügen neuer Verhaltensweisen zu den vorhandenen Datenstrukturen einfach ist.
Lieblingszitat des Kapitels: „In jedem System werden wir manchmal die Flexibilität haben wollen, neue Datentypen hinzuzufügen, also bevorzugen wir Objekte für diesen Teil des Systems. Ein anderes Mal möchten wir die Flexibilität haben, neue Verhaltensweisen hinzuzufügen. Daher bevorzugen wir für diesen Teil des Systems Datentypen und Prozeduren.“
Kapitel sieben: Fehlerbehandlung
Die Behandlung von Fehlern ist unerlässlich, und davon gibt es bei der Programmierung in der Regel viel. Dennoch sollte sie nicht die eigentliche Absicht des Codes verbergen. Verwenden Sie daher eher Erwartungen als Rückgabewerte.
Die Ausnahmen sollten informativ sein und objektive, kontextbezogene und detaillierte Angaben zum Fehlertyp enthalten, damit jemand, der die Fehlermeldung erhält, eine effektive Fehlersuche durchführen kann.
Ausnahmen definieren den Anwendungsbereich Ihres Programms. Wenn Sie Code in den try-Teil einer try-catch-finally-Anweisung implementieren, drücken Sie damit aus, dass die Ausführung an jedem beliebigen Punkt abgebrochen und an der catch-Anweisung neu gestartet werden kann.
Wenn Sie die APIs von Drittanbietern in eine dünne Abstraktionsschicht verpacken, wird es einfacher, eine Bibliothek in Zukunft gegen eine andere auszutauschen und die Bibliothek während des Testens zu simulieren.
Lieblingszitat des Kapitels: „Sauberer Code ist lesbar, aber er muss auch robust sein. Dies sind keine widersprüchlichen Ziele. Wir können robusten, sauberen Code schreiben, wenn wir die Fehlerbehandlung als ein besonderes Anliegen betrachten.“
Kapitel acht: Grenzen
Der Code von Drittanbietern hilft Ihnen dabei, mehr Funktionalität in kürzerer Zeit zu liefern. Es ist nicht Ihre Aufgabe, den Code von Drittanbietern zu testen, aber es sollte Ihr Interesse sein, Tests für den von Ihnen verwendeten Code von Drittanbietern zu schreiben.
Lerntests sind präzise Experimente, die Ihnen helfen, Ihr Verständnis zu verbessern. Lerntests bestätigen, dass die von Ihnen verwendeten Drittanbieterpakete so funktionieren, wie Sie es erwarten. Es gibt keine Garantie dafür, dass der Code von Drittanbietern in Kombination mit Ihren Anforderungen kompatibel bleibt.
Gute Software lässt sich ohne große Investitionen und Nacharbeit ändern. Wenn Sie Code verwenden, der sich Ihrer Kontrolle entzieht, müssen Sie besonders vorsichtig sein, um Ihre Investitionen zu schützen und sicherzustellen, dass künftige Änderungen überschaubar sind.
Grenzen von Drittanbietern werden durch einige Stellen im Code verwaltet, die auf sie verweisen.
Vermeiden Sie es, dass zu viel von Ihrem Code über die Details von Drittanbietern erfährt. Es ist besser, sich auf etwas zu verlassen, das Sie kontrollieren können, als auf etwas, das Sie nicht kontrollieren können.
Lieblingszitat des Kapitels: „Wir sollten es vermeiden, zu viel von unserem Code über Einzelheiten von Dritten wissen zu lassen. Es ist besser, sich auf etwas zu verlassen, das Sie kontrollieren, als auf etwas, das Sie nicht kontrollieren, damit es nicht Sie kontrolliert.“
Kapitel neun: Einheitstests
Bei der testgesteuerten Entwicklung müssen Sie Unit-Tests schreiben, bevor Sie Produktionscode schreiben. Sie können keinen produktiven Code schreiben, bevor Sie nicht einen fehlgeschlagenen Unit-Test geschrieben haben. Der Testcode muss genauso sauber sein wie der Produktionscode, mit wenigen Ausnahmen, die in der Regel den Speicher oder die Effizienz betreffen.
Achten Sie darauf, Ihre Tests sauber zu halten, sonst verlieren Sie sie. Und wenn sie fehlen, verlieren Sie das Einzige, was Ihren Code wiederverwendbar, flexibel und wartbar macht. Sie werden keine Angst haben, Codeänderungen vorzunehmen, wenn Tests vorhanden sind, aber ohne sie ist jede Änderung ein möglicher Fehler.
Die Lesbarkeit ist das, was einen Test sauber macht. Die Lesbarkeit ist bei Unit-Tests vielleicht sogar noch wichtiger als bei Produktionscode. Klarheit, Einfachheit und Dichte des Ausdrucks machen Tests lesbar. In einem Test müssen Sie mit so wenigen Ausdrücken wie möglich viel sagen.
Normalerweise möchten Sie in jeder Testfunktion ein einziges Konzept testen. Sie möchten keine ausgedehnten Testfunktionen, die eine Sache nach der anderen testen.
Genau wie der Produktionscode sind auch die Tests für die Robustheit des Projekts entscheidend. Tests sind notwendig, weil sie die Wiederverwendbarkeit, Wartbarkeit und Flexibilität des Codes verbessern und erhalten. Halten Sie Ihre Tests sauber und sorgen Sie dafür, dass sie aussagekräftig und kurz sind. Entwickeln Sie APIs, die als domänenspezifische Sprache fungieren, die Sie beim Schreiben von Tests unterstützt.
Lieblingszitat des Kapitels: „Tests müssen zeitnah geschrieben werden. Unit-Tests sollten kurz vor dem Produktionscode geschrieben werden, der sie erfolgreich macht.“
Kapitel 10: Klassen
Klassen müssen mit einer Liste von Variablen beginnen. Öffentliche statische Konstanten sollten an erster Stelle stehen, dann private statische Variablen, gefolgt von privaten Instanzvariablen. Setzen Sie die privaten Hilfsprogramme, die von einer öffentlichen Funktion aufgerufen werden, direkt dahinter.
Die erste Regel für Klassen ist, dass sie klein sein müssen. Genau wie bei Funktionen ist die wichtigste Regel für die Erstellung von Klassen, dass sie klein sein müssen. Aber die eigentliche Frage ist immer: „Wie klein?“. Bei Funktionen berechnen Sie die Größe durch das Zählen der physischen Zeilen. Bei Klassen messen Sie die Größe durch das Zählen von Verantwortlichkeiten.
Klassen müssen eine kleine Anzahl von Instanzvariablen haben. Jede Methode einer Klasse sollte eine oder mehrere dieser Variablen kontrollieren. Je mehr Variablen eine Methode beeinflusst, desto stärker ist sie mit ihrer Klasse verbunden.
Verwenden Sie in Ihrer Anwendung lieber viele kleine Klassen als ein paar große Klassen. Dies minimiert die Menge an Informationen, die ein anderer Entwickler bei der Arbeit an einer bestimmten Aufgabe verstehen muss.
Lieblingszitat des Kapitels: „Eine Klasse oder ein Modul sollte einen, und nur einen, Grund haben, sich zu ändern.“
WIE DIESES BUCH SOFTWAREENTWICKLERN HELFEN KANN?
„Clean Code“ von Robert C. Martin kann Softwareentwicklern helfen, die Qualität ihres Codes zu verbessern. Es bietet praktische Ratschläge und Richtlinien, wie man lesbaren, wartbaren und effizienten Code schreibt. Das Buch behandelt Themen wie Benennung, Kommentierung, Formatierung und Testen und betont die Bedeutung von Einfachheit, Klarheit und Konsistenz bei der Codierung. Durch die Befolgung der in diesem Buch dargelegten Prinzipien können Entwickler technische Schulden reduzieren, die Produktivität steigern und Software erstellen, die leichter zu verstehen, zu ändern und zu erweitern ist. Es bietet Softwareentwicklern einen umfassenden Ansatz für die Programmierung, mit dem sie ihre Fähigkeiten verbessern und die Kosten für die Wartung senken können. Dieses Buch hilft Programmierern, Code zu schreiben, der in Zukunft leicht zu ändern und zu refaktorisieren ist. Es ist eine Pflichtlektüre für jeden Softwareentwickler, der ein besserer Programmierer werden will.