Leitfragen und Übungsaufgaben zum roten Grad des Clean-Code-Developers
https://bildung.social/@oerinformatik/111334923701270625
https://oer-informatik.de/cleancode-rotergrad-uebung
tl/dr; (ca. 60 min Bearbeitungszeit): Leitfragen und Übungsaufgaben zu CleanCode: Der Artikel enthält eine Reihe von Leitfragen zum Verständnis der Prinzipien (DRY, KISS, BoPO, FCol, IOSP) und Praktiken (Boy Scout, Root Cause, VCS, Refactoring, Reflection), die im roten Grad des Clean-Code-Developers zusammengefasst sind. Am Ende findet sich eine praktische Übungsaufgabe, bei der CleanCode-Prinzipien angewendet werden sollen. (Zuletzt geändert am 06.11.2023)
Um die Leitfragen beantworten zu können, solltest Du Dich zunächst mit dem roten Grad des Clean Code Developers beschäftigen - oder auf anderem Weg mit den Prinzipien (DRY, KISS, BoPO, FCol, IOSP) und den Praktiken (Boy Scout, Root Cause, VCS, Refactoring, Reflection) vertraut machen.
Was versteht man bei der Programmierung unter Refaktorisierung?
Refaktorisieren bedeutet, den Quellcode zu verbessern, ohne die Funktionalität zu verändern. Der Quellcode wird dabei dahingehend geändert, dass er Coding Conventions entspricht, übersichtlicher, lesbarer, wartbarer wird. Er wird mit Kommentaren ergänzt oder von überflüssigen Kommentaren und Codeabschnitten befreit.
Das Designprinzip Don’t repeat yourself (DRY) schlägt vor, dass Redundanzen aus dem Code entfernt werden sollen. Unter welchen Umständen sollten Wiederholungen nicht refaktorisiert werden, also gegen das Prinzip verstoßen werden?
Immer dann, wenn andere Design-Prinzipien dadurch verletzt werden, sollte man überprüfen, ob Wiederholungen das geringere Übel sind.
Clean Code kenn das Keep it simple, stupid (KISS)-Prinzip. Welche Praktiken helfen, das KISS-Prinzip einzuhalten?
Auf einfache Lösungen kommt man selten allein. Daher sind vor allem Review-Techniken, die hierbei helfen: Pair Programming, Team-Reviews, Rubber-Duck-Review.
Albert Einstein wird ein Zitat zugeschrieben, dass das Keep it simple, stupid (KISS)-Prinzip gut beschreibt. Wie lautet es?
Alles sollte so einfach wie möglich gemacht werden, aber nicht einfacher.
Auch für Datenstrukturen gilt das KISS-Prinzip. An welches Beispiel kann man das Prinzip erläutern?
Bei einfachen Aufzählungen können Datentypen verwendet werden, die genau nur das tun (z.B.
ENUM
) anstatt komplexere Strukturen zu verwenden (wie etwa die ObjektsammlungenList
oderCollection
- Bezeichner natürlich in jeder Sprache anders).Welche Gründe werden angeführt, auf Optimierungen zu verzichten?
Auf Optimierungen kann verzichtet werden, wenn:
andere Prinzipien leiden (wie die Verständlichkeit, Fehlerrobustheit,…)
wenn die Optimierung keine Kundenanforderung betrifft
Welche Voraussetzungen müssen vorliegen, damit optimiert werden darf?
Optimiert werden sollte nur, wenn durch Messung nachgewiesen wurde, dass die betreffende Stelle tatsächlich der Flaschenhals (oder Problemursache) ist.
Das Favour Composition over Inheritance (FCoI) - Prinzip spricht sich dagegen aus, in jedem Fall Vererbung zur Erweiterung zu nutzen. Welche Probleme entstehen bei der Vererbung, die so verhindert werden sollen?
Innerhalb von Vererbungsstrukturen ist der Codetausch zur Laufzeit nicht möglich. Abhängigkeiten der Kindklasse von der Elternklasse können nicht gelöst werden. Die Klassen sind so nicht isoliert testbar. Diese feste Kopplung erhöht die Komplexität. Durch lose Kopplung (per Aggregation/Komposition) können diese Nachteile verhindert werden.
Erkläre, warum die Begriffe whitebox reuse und blackbox reuse im Zusammenhang mit dem FCoI-Prinzip geraucht werden!
Whitebox-Reuse steht für Vererbung. Bei der Vererbung sind die wiederverwendeten Codebestandteile von Beginn an klar und transparent: sie können nicht getauscht werden.
Wird Code über lose Kopplung (Aggregation/Komposition) wiederverwendet, so ist nicht transparent, welcher Code genutzt wird: das Aggregat kann getauscht werden. Man sieht also nicht, welcher Code angefügt wird. Es ist eine Blackbox.
Warum kann man sagen, das Vererbung die Kapselung zerstört?
Bei Vererbung hängt die Kindklasse von Details/Implementierung der Elternklasse ab. Änderungen in der Elternklasse können die Funktionalität der Kindklasse zerstören.
Beispiel: die Elternklasse
Address
hat ein gekapseltes Attributphonenr
, das über den Setter oder über den Konstruktor (der den Setter aufruft) gesetzt werden kann. Eine KindklasseInternationanAddress
spezialisiert den Setter, um immer in der internationalen Variante+49 ..
abzuspeichern. Die Kindklasse geht es davon aus, dass die Elternklasse alle neuen Attributwerte über den Setter-Aufruf speichert. Wird dieses Verhalten in der Elternklasse geändert (z.B. indem der Konstruktor direkt das Attribut schreibt), funktioniert die Kapselung des Attributs in der Kindklasse nicht mehr so, wie erwartet. (Fragile base class-Problem)Im Integration Operation Segregation Principle (IOSP) wird von den Nachteilen tiefer Hierarchien (also viele Einrückungsebenen, Blöcken) gesprochen. Was ist so schlecht daran?
Bei tiefen Hierarchien, also Code, der mit vielen verschachtelten Codeblöcken auf vielen Ebenen arbeitet, leidet die Lesbarkeit. Die wesentliche und wichtigste Struktur liegt oft auf der unteren Ebene - diese ist dann über viele Codezeilen verteilt. Codeblöcke, die in einer Ebene sind, können nicht auf Anhieb zugeordnet werden. Es kommt so häufig vor, dass z.B.
else
-Zweige einem falschenif
-Statement zugeordnet werden.In welche Kategorien werden Methoden gemäß IOSP aufgeteilt?
Methodenaufrufe, die Abläufe gliedern = Integration
Logik von den Abläufen getrennt: Transformationen, Kontrollstrukturen, I/O = Operation
Welche Größenordnung an Codezeilen wird für Methoden angegeben?
Im Text sind 10, 20, 30 Zeilen angegeben. Eine absolute Maximalgröße ist jedoch nicht festlegbar. Richtwerte können im Rahmen der Coding Conventions im Team abgestimmt werden.
Wie helfen mir Methodennamen, das IOS-Prinzip einzuhalten?
Findet sich schnell ein Methodenname, der alles beschreibt, was in der Methode passiert ist IOSP gewahrt. Neigt man dazu, im Methodennamen ein “UND” einzufügen, ist es entweder eine Integrationsmethode - oder sie sollte weiter aufgeteilt werden.
Als eine Praktik wird die Pfadfinderregel genannt (“Boy Scout Rule”). Wie lautet die Pfadfinderregel im Original?
“Always leave the code you are working on a little bit better than you found it.”
Bei den Pfadfindern ist es der Ort (z.B. Zeltplatz), den sie sauberer verlassen sollen, als sie ihn vorgefunden haben.
Was besagt die “Broken Windows Theorie” hinsichtlich Softwareentwicklung?
Im Original besagt die Theorie, dass kleine Zerstörungen (z.B. kaputte Fensterscheiben) zur Folge haben, dass auch andere Dinge zerstört werden (am Ende: ganze Stadtviertel). Daher sollte man auch kleine Schäden schnell beheben. In der Softwareentwicklung bedeutet dies, dass kleine Ungenauigkeiten, Abkürzungen oder unsauberer Code dafür sorgen, dass sich andere ermutigt fühlen, das Chaos zu vergrößern. Daher sollte man immer für aufgeräumten, sauberen Code sorgen.
Warum löst es nicht nur das Problem nicht, sondern ist auch gefährlich, das Symptom zu bearbeiten und nicht den Root Cause?
Durch Symptombekämpfung werden Fehler versteckt. Gegebenenfalls treten sie erst wieder zutage, wenn es fatale Auswirkungen hat. Da das eigentliche Problem nicht mehr offensichtlich ist, verbleibt es wie eine tickende Zeitbombe im System.
Welche einfachen Refaktorisierungsmuster gibt es, die man von Beginn an (auch als Berufsanfänger) beherzigen kann und sollte?
Methoden extrahieren
Umbenennen
Welche Techniken helfen, Reflexionen im Alltag einzuplanen?
Kleinschrittige Planung
Reflexion nach jedem Schritt
Abends / kurz vor Feierabend: Habe ich alle meine Aufgaben erledigt? Wie habe ich meine Aufgaben erledigt?
Übungsaufgabe Clean Code
Um benötige Heizwärme unterschiedlicher Jahre vergleichen zu können, werden die Abnahmemengen des bezogenen Energieträgers klimabereinigt. Dazu wird die Heizenergie über die Außentemperatur normiert. Es wird davon ausgegangen, dass Heizungen nur bei Außentemperaturen unterhalb einer “Heizgrenztemperatur” (hier beispielhaft heizgrenze=14\rm{^{\circ}C}) aktiviert sind. (Tage, bei denen das zutrifft, sind in der Tabelle mit TRUE
in der Spalte “Heiztag” markiert).
Unterhalb der Heizgrenztemperatur steigt der Heizbedarf proportional zu Temperaturdifferenz aus der jeweiligen Außentemperatur (tm \_temp[i]) und einer angesetzten Raumtemperatur (z.B. raumtemp=18\rm{^{\circ}C}). Daher werden zur Normierung diese Temperatursummen für alle Tage addiert, an denen die Heizgrenztemperatur unterschritten wird.
Gradtagszahl=\sum_{i=0}^{anzahl\_tage-1}{( tm \_ temp[i] - raumtemp)\ if\ (tm \_temp[i] < heizgrenze)\ else\ 0}
Die Werte können beispielsweise so aussehen:
Index | Datum | Tagesmittel der Außentemperatur in ^{\circ}C |
Gasbedarf in kWh |
Heiztag | Gradtagszahl in ^{\circ}C |
---|---|---|---|---|---|
tag | datum | tm \_temp[i] | gasverbrauch | ||
2920 | 12.09.2022 | 16,1 | 2,946 | FALSE |
0,0 |
2921 | 13.09.2022 | 18,3 | 3,160 | FALSE |
0,0 |
2922 | 14.09.2022 | 13,4 | 19,704 | TRUE |
4,6 |
2923 | 15.09.2022 | 14,2 | 2,89 | FALSE |
0,0 |
2924 | 16.09.2022 | 12,6 | 22,429 | TRUE |
5,4 |
2925 | 17.09.2022 | 11,2 | 28,011 | TRUE |
6,8 |
2926 | 18.09.2022 | 10,2 | 31,425 | TRUE |
7,8 |
Die folgende Python-Funktion berechnet die Heizkennziffer vereinfacht mit folgender Formel:
Heizkennziffer=\frac{\sum{Gasbedarf}}{Gradtagszahl}
Folgender Quellcode liegt dafür bislang vor:
def heizkennziffer(gesamt_gasverbrauch, gesamt_temp_profil,
start_tag, tage_anzahl, raumtemp, heizgrenze):
gasverbrauch = gesamt_gasverbrauch[start_tag:start_tag+tage_anzahl]
temp_profil = gesamt_temp_profil[start_tag:start_tag+tage_anzahl]
g = 0 # Gradtagszahl
for tagesmittel_temp in temp_profil:
if tagesmittel_temp < heizgrenze:
g += raumtemp - tagesmittel_temp
v = 0 # Gasverbrauch
for tagesverbrauch in gasverbrauch:
v += tagesverbrauch
if (g>0):
kennziffer = v/g
else:
kennziffer = 999
return kennziffer
Der vorige Codeausschnitt wurde noch nicht mithilfe von Clean-Code Prinzipien und Praktiken refaktorisiert.
Was versteht man unter Refaktorisierung? Nennen Sie eine Definition sowie zwei einfache Refaktorisierungsmuster.
Welche Änderungen können sie bei dem dargestellten Quellcode anwenden, damit das IOSP-Prinzip umgesetzt wird? Nennen Sie in einem Satz zwei Änderungen, die sie hierfür vornehmen würden (sie können auch oben im Quellcode Hinweise eintragen).
Im obigen Codeausschnitt wird zweimal eine Schleife über alle beobachteten Tage durchlaufen, was sich zusammenfassen lässt. Erklären Sie in einem Satz hinsichtlich des “Beware of Premature Optimization”-Prinzips, warum es sinnvoll sein kann, diese Zusammenfassung nicht vorzunehmen!
Links und weitere Informationen
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Leitfragen und Übungsaufgaben zum roten Grad des Clean-Code-Developers” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/cleancode-rotergrad-uebung veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/design-prinzipien/clean-code. Stand: 06.11.2023.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]