# Implementing for Maintainability > **We are NOT DONE when the code works!** >_Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live_ > > ~_John F. Woods_ ## Materials - [Refactoring _by Martin Fowler_](https://learning.oreilly.com/library/view/refactoring-wie/9783958459434/) - [refactoring catalog](https://refactoring.com/catalog/) - [Clean Code _by Uncle Bob_](https://learning.oreilly.com/library/view/clean-code/9783826655487/) - ## Introduction - Code wird häufiger gelesen als geschrieben - **Refactoring** ist ein - Prozess, der die Struktur des Codes verbessert, ohne die Funktion zu verändern - disziplinierter Weg den Code zu bereinigen und so die Chance auf Bugs zu minimieren - **Code Smells** - Charakteristik im Code, das etwas falsch sein könnte - Nicht alle Zeichen von Code Smells sind zwingend ein Zeichen von schlechtem Code ## Refactoring ### Rename Variables ```c++ double a = height * width ↓ double area = height * width ``` ### Replace magic literals ```c++ 2 * 3.14 * radius ↓ 2 * pi * radius ``` ### Extract Variable ```c++ void renderBanner(){ if((platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1) && wasInitialized() && resize > 0){ //do something } } ↓ void renderBanner() { final bool isMacOs = platform.toUpperCase().indexOf("MAC"") > -1; final bool isIE = browser.toUpperCase().indexOf("IE") > -1; final bool wasResized = resize > 0; if (isMacOs && isIE && wasResized){ //do something } } ``` ### Extract Function ```c++ void printOwing(){ printBanner(); //prinz details std::cout << "name: " << name << std::endl; std::cout << "amount: " << getOutstanding() << std::endl; } ↓ void printOwing(){ printBanner(); printDetails(getOutstanding()); } void printDetails(double outstanding){ std::cout << "name: " << name << std::endl; std::cout << "amount: " << outstanding << std::endl; } ``` ## Meaningful Names - Namen im Code sollten immer die Intention der Variable/Funktion/Klasse zeigen - Umbenennen, falls nicht - Ein Wort pro Konzept - immer getName() bspw. | Solution Domain Names | Problem Domain Names | |-----------------------|----------------------------------------------------------------------| | Developer-Sprache | Code mit Kundenkontakt sollte verständlich für nicht-Entwickler sein | ## Functions - Sollten klein sein - Nur eine Zeile im body von: - if/else - for-loop - while-loop - Sollten nur eine Aufgabe haben - Geschafft, wenn - es nicht möglich ist eine Funktion daraus zu extrahieren - sie keine Side-Effects haben - sie entweder auf etwas antworten ODER etwas tun - switch-Statements nur, wenn - sie nur einmal vorkommen - sie polymorphe Objekte erzeugen - sie nicht für den Rest des Systems sichtbar sind > **Don't Repeat Yourself! (DRY)** ### Arguments - Weniger Argumente machen den Code lesbarer - **Flag arguments are ugly** - Boolean in Funktion mitgeben zeigt, dass die Funktion mehrere Sachen macht → :( - Ideale Anzahl an Argumenten ist 0 - 1 Argument (**monadic**) - Fragen an ein Argument - _bspw. ```boolean file exists(String fileName)```_ - Operation an argument ausführen und Ergebnis zurückgeben - Events - Kein Rückgabewert - 2 Argumente (**dyadic**) - schwieriger zu verstehen - Sind manchmal trotzdem sinnvoll - _bspw. wenn man einen Punkt (x, y) mitgibt_ - 3 Argumente (**triadic**) (_sollten, wenn möglich, vermieden werden_) - sollten vermieden werden - Mehr Argumente (**polyadic**) (_sollten vermieden werden_) ### Argument Objects - Wenn eine Funktion mehr als 2-3 Argumente braucht - Objekt erstellen, welches mehrere Argumente zusammenfasst - _bspw. ```double x, double y → Point center``` ### Argument Lists - Falls beliebig viele Argumente mitgegeben werden sollen, diese aber identisch behandelt werden - Zählen als "ein" Argument - _bspw. ```String.format("\%s worked \%.2 hours.", name, hours)``` - Ist dyadic ## Comments > **Don't comment bad code - rewrite it!** > ~_B.W. Kernighan and P.J. Plaugher_ ### Good comments - gibt es, aber die besten sind die, die du nicht mehr schreiben musst #### Legal comments - sind häufig nötig und verständlich - sollten trotzdem vermieden werden, indem auf ein Lizenz-File verwiesen wird - _bspw. Copyright etc._ #### Informative comments - manchmal sollte man basic Informationen mitgeben, um die Sprache zu verstehen - _bspw. ```//format matched kk:mm:ss``` ```"\\d*:\\d*:\\d*```_ #### Explanation of Intent - _bspw._ ![image_49.png](image_49.png) #### Clarification - _bspw._ ![image_50.png](image_50.png) #### Warning of Consequences - _bspw._ ![image_51.png](image_51.png) #### TODO Comments - Sollten auch vermieden werden, einfach fertig machen :) #### Amplification - Manchmal zeigen Kommentare wie wichtig etwas ist - _bspw._ ![image_52.png](image_52.png) ### Bad Comments - Wenn der Code eh schon verständlich genug ist - Zu viele Informationen - Auskommentierter Code - Nicht verständliche Verbindung zwischen Code und Kommentar ## Formatting / Style Guides > Der beste Stil ist der, der durchgängig ist ## Classes - Sollten klein sein - Wird gemessen in Responsibilities - **Single Responsibility Principle (SRP)** - Klassen sollten nur EINE Aufgabe haben - Führt zu high cohesion | low cohesion | high cohesion | |------------------------------------------------------------------------|-------------------------------------------------------------------------| | bewirbt Schwierigkeit zu warten, testen, wiederverwenden, zu verstehen | bewirbt Robustheit, Verständlichkeit, Wiederverwendbarkeit, Reliability | ## Loose Coupling > **Law of Demeter** > > _Talk to Friends, not to Strangers_ - Ein Freund eines Freundes ist ein Fremder - Minimiere den Grad von Interdependencies ![image_53.png](image_53.png)