215 lines
6.2 KiB
Markdown
215 lines
6.2 KiB
Markdown
# 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._ 
|
|
|
|
#### Clarification
|
|
- _bspw._ 
|
|
|
|
#### Warning of Consequences
|
|
- _bspw._ 
|
|
|
|
#### TODO Comments
|
|
- Sollten auch vermieden werden, einfach fertig machen :)
|
|
|
|
#### Amplification
|
|
- Manchmal zeigen Kommentare wie wichtig etwas ist
|
|
- _bspw._ 
|
|
|
|
### 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
|
|
|
|

|
|
|
|
|