Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code...

29
Clean Code

Transcript of Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code...

Page 1: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Clean Code

Page 2: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

a short summary of

Page 3: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

The Future of Code

• Model-based Development

• Automatic Code Generation

• Scratch (MIT)

• Domain Specific Languages

• Code vs. Specification

Page 4: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Why should I care about Clean Code?

• Bad Code decreases productivity.• Management: “We simply hire more staff !”

– unfamiliar with code– no clear design– � mess increases

[1]

Page 5: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Apropos Manpower: Brooks’s Law

Adding manpower

to a late software project

makes it later.

[Fred Brooks,The Mythical Man-Month]

Turing-PreisträgerFrederick P. Brooks Jr. (* 1931)

Bild: Wikipedia

Page 6: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Now, what is Clean Code?

Clean code is simple and direct. Clean code

reads like well-written prose. Clean code never

obscures the designer’s intent but rather is full of

crisp abstractions and straightforward lines of

control.

Grady Booch (UML)

Page 7: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Namingpublic List<int[]> getThem() {

List<int[]> list1 = new ArrayList<int[]>();

for (int[] x : theList)

if (x[0] == 4)

list1.add(x);

return list1;

}

Page 8: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Namingpublic List<int[]> getFlaggedCells() {

List<int[]> flaggedCells = new ArrayList<int[]>();

for (int[] cell : gameBoard)

if (cell[STATUS_VALUE] == FLAGGED)

flaggedCells.add(cell);

return flaggedCells;

}

Page 9: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Namingpublic List<Cell> getFlaggedCells() {

List<Cell> flaggedCells = new ArrayList<Cell>();

for (Cell cell : gameBoard)

if (cell.isFlagged())

flaggedCells.add(cell);

return flaggedCells;

}

Page 10: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Namingpublic List<Cell> getFlaggedCells() {

List<Cell> flaggedCells = new ArrayList<Cell>();

for (Cell cell : gameBoard)

if (cell.isFlagged())

flaggedCells.add(cell);

return flaggedCells;

}

BTW: This is the same in Scala! ;-)

List[Cell] getFlaggedCells = gameBoard.take(_.isFlagged)

Page 11: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells

• Kommentare– Wenn Code dokumentiert werden muss:

Code neu schreiben (Variablen, Funktionen umbenennen)– Einrückung & Formatierung– Class Header– C2: Obsolete Comment

• Code u. Kommentare müssen übereinstimmen

– C3: Redundant Comment• Vermeide: i++; //increment i

– C4: Poorly Written Comment• Rechtschreibung, Grammatik, Satzzeichen

– C5: Commented-Out Code• Löschen (Versionskontrolle!)

Page 12: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (2)

• Methoden

– Benennung: was macht die Methode? � Verb

– 1 Methode: 1 Aufgabe � ansonsten aufteilen

– Achtung auf Sideeffects

– 1 Methode: 1 Abstraktionsniveau

– Wenig Argumente (F1)

– Dead Code löschen (Versionskontrolle) (F4)

– Corner cases bedenken und testen (G3)

Page 13: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (3)

• Code Duplication (G5)– Widerspricht DRY (Andy Hunt). “Once, and only once”

(K.Beck)

– Arten• Gleicher/Ähnlicher Code in einer Klasse

– Extrahiere eine Methode

• Gleicher/Ähnlicher Code in Subklassen– Ziehe den Code in die Basisklasse

• Gleicher/Ähnlicher Code in verschiedenen Klassen– Extrahiere den Code und erstelle eine Hilfsklasse

– Design-Patterns helfen (sh. später)

Page 14: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (4)

• Code at Wrong Level of Abstraction (G6)– Good software design requires that we separate concepts at different

levels and place them in different containers.

– Container: class, file, module, component

public interface Stack {

Object pop() throws EmptyException;

void push(Object o) throws FullException;

double percentFull();

class EmptyException extends Exception {}

class FullException extends Exception {}

}

�Difficult in general!• Base Class Depending no their Derivatives (G7)

– Basisklassen sollen nichts über Subklassen wissen

Page 15: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (5)

• Too much information (G8)– Öffentliche Schnittstelle klein halten– Wenig preis geben, Implementierung verstecken

• Dead Code (G9)– If, switch/case, try/catch– Mit Hilfe von Tools erkennbar � Code löschen

• Vertical Separation (G10)– Lokale Variablen dort deklarieren wo sie gebraucht werden

• Clutter (G12)– Leerer Default-Konstruktor– Ungenützte Variablen, Funktionen

Page 16: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (5b)

• Use Explanatory Variables(G19)

– Lesbarkeit durch Hilfsvariablen erhöhen.

• Auch um Anzahl von Casts zu reduzieren (sh. später)

Matcher match = headerPattern.matcher(line);

if(match.find())

{

String key = match.group(1);

String value = match.group(2);

headers.put(key.toLowerCase(), value);

}

Page 17: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (6)

• Follow Standard Conventions (G24)– Lege für das Team Richtlinien fest und kommuniziere sie

– Coderrichtlinien (Code Conventions) geben vor:• Namenwahl (z.B. Klassennamen als Substantive in CamelCase, …)

• Strukturierung (z.B. Einrückungen, Zeilenumbruch, max. Zeilenlänge, …)

• Kommentierung (z.B. Alle Kommentare in Englisch, Aufbau,…)

– Zusätzlich• Äußere Form (z.B. GUI Design, Style Guide, erlaubte Controls, …)

• Bibliotheken (z.B. Erlaubte Libraries, Versionen, …)

• Compiler-Einstellungen (z.B. Nur Release Versionen,…)

Page 18: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (7)

• Replace Magic Numbers with Named Constants (G25)– Zahlen und Strings:private final int WIDTH = 80;

private final String CONFIG_FILE = “config.xml”

• Encapsulate Conditionals (G28)– Gut benannte Hilfsvariablen/-methoden einführen:

if (timer.hasExpired() && !timer.isRecurrent())

vs.

if (shouldBeDeleted(timer))

Page 19: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (8)

• Functions Should Descend Only One Level of Abstraction (G34)

Page 20: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (9)

– Keep Configurable Data at High Levels (G35)

public static void main(String[] args) throws Exception

{

Arguments arguments = parseCommandLine(args);

...

}

public class Arguments

{

public static final String DEFAULT_PATH = ".";

public static final String DEFAULT_ROOT = "FitNesseRoot";

public static final int DEFAULT_PORT = 80;

public static final int DEFAULT_VERSION_DAYS = 14;

...

}

Page 21: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (10)

– Avoid Transitive Navigation (G36)• = Write “shy code” [The Pragmatic Programmer, AW, 2000].

• Module sollen nur über ihre direkten Kollaborator-Module bescheid wissen müssen, nicht über die Verflechtung des gesamten Systems.

Statt a.getB().getC().doSomething();

� myCollaborator.doSomething();

Page 22: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (11)

– Choose Descriptive Names (N1)• Lesbarkeit zu 90% von Namen abhängig

• Sinnvolle Bezeichnung wählen und konsistent halten

– Use Long Names for Long Scopes

• Je länger eine Variable gültig ist desto länger und aussagekräftig sollte ihr Name sein

• Der Klassiker i ist duraus ok für Schleifenvariablen

Page 23: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (11’2)public int x() {

int q = 0;

int z = 0;

for (int kk = 0; kk < 10; kk++) {

if (l[z] == 10) {

q += 10 + (l[z + 1] + l[z + 2]);

z += 1;

} else if (l[z] + l[z + 1] == 10) {

q += 10 + l[z + 2];

z += 2;

} else {

q += l[z] + l[z + 1];

z += 2;

}

}

return q;

}

public int score() {

int score = 0;

int frame = 0;

for (int frameNr = 0; frameNr < 10; frameNr ++) {

if (isStrike(frame)) {

score += 10 + nextTwoBallsForStrike(frame);

frame += 1;

} else if (isSpare(frame)) {

score += 10 + nextBallForSpare(frame);

frame += 2;

} else {

score += twoBallsInFrame(frame);

frame += 2;

}

}

return score;

}

Page 24: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (12)

– „Public“ everywhere• Public: nur was wirklich „von aussen“ sichtbar sein soll;

Felder, Methoden, aber auch ganze Klassen, Konstruktoren

• Rest: private oder default-modifier

– Excessive Casting

Page 25: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (12’2)private void changePortAlignment(Object value) {

switch ((int)value) {

case 0:

((Port) _element).setIndex(((Actor)((Port)

_element).getParent()).getCountNorth() + 1);

break;

case 1:

((Port) _element).setIndex(((Actor)((Port)

_element).getParent()).getCountSouth() + 1);

break;

//..

default:

break;

}

((Port) _element).setAlignment((int) value);

}

Page 26: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (12’3)private void changePortAlignment(Object value) {

Port port = (Port) _element;

Actor parent = (Actor) port.getParent();

switch ((int)value) {

case NORTH:

port.setIndex(parent.getCountNorth() + 1);

break;

case SOUTH:

port.setIndex(parent.getCountSouth() + 1);

break;

//..

default:

break;

}

port.setAlignment((int) value);

}

… with some aux. Variables (G19) and named constants (G25)

Page 27: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (12’4)private void changePortAlignment(Object value) {

Port port = (Port) _element;

Actor parent = (Actor) port.getParent();

Alignment align = Alignment.valueOf(value.toString());

port.setIndex(parent.getCountAlign(align));

port.setAlignment(align);

}

public enum Alignment {EAST, NORTH, SOUTH, WEST};

… with some more restructuring and enums

Page 28: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells (13)

• Exception Handling

Page 29: Clean Code · Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions

Code Smells

Making code readable requires a dedication

to continuous improvement.