clean, effective java
DESCRIPTION
In deze presentatie die ik gaf aan collega's, licht ik enkele topics toe uit deze boeken: - Robert C. Martin, Clean Code - Joshua Bloch, Effective JavaTRANSCRIPT
![Page 1: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/1.jpg)
Clean, effective Java
Bert Van Vreckem
![Page 2: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/2.jpg)
2
![Page 3: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/3.jpg)
3
?
![Page 4: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/4.jpg)
4
(TODO)
![Page 5: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/5.jpg)
5
![Page 6: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/6.jpg)
6
![Page 7: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/7.jpg)
7
Josh Bloch
![Page 8: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/8.jpg)
8
Inhoud EJ (2nd Ed, 2008)
● Creatie objecten● Gemeensch. methods● Klassen en interfaces● Generieke klassen● Enums, annotaties● Methods
● Algemene programmeertips
● Foutafhandeling● Concurrency● Serialisatie
● 78 “items” (EJ#nn)
![Page 9: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/9.jpg)
9
![Page 11: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/11.jpg)
11
Inhoud CC(2009)
● Naamgeving● Functies● Commentaar● Formattering● Objecten &
datastructuren● Foutafhandeling● Grenzen
● Unit tests● Klassen● Systemen● “Emergent design”● Iteratieve verfijning● Refactoring case● Indicatoren van
slechte code
![Page 12: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/12.jpg)
12
Wat is “heldere” code?
![Page 13: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/13.jpg)
13
Doel:
● Disseminatie● Discussie● Feedback
PS. Koop de boeken! (vakgroepbib?)
![Page 14: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/14.jpg)
14
Conventies
● Kleurtjes:● “good practice”● “bad practice”● nadruk
● Verwijzingen:● CC5 = Clean Code, hoofdstuk 5● EJ5 = Effective Java, hoofdstuk 5● EJ#5 = Effective Java, item 5
![Page 15: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/15.jpg)
15
Onderwerpen
Klassen
Functies
Unit tests
Ontwerp
Stijl
![Page 16: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/16.jpg)
16
Klassen
![Page 17: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/17.jpg)
17
Klassen
● EJ4 “Classes and Interfaces”● CC6 “Objects and Data Structures”● CC10 “Classes”
![Page 18: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/18.jpg)
18
Richtlijnen voor klassen (CC10)
● Klassen moeten klein zijn● Geen “God-klassen” (vb. DomainContoller!)● “Single Responsibility Principle”: er is maar 1 reden
om de klasse te wijzigen● Cohesie: klein aantal instantievariabelen, methods
manipuleren meerdere instantievariabelen
![Page 19: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/19.jpg)
19
Beperk “mutability” (EJ#15)
● Geen mutators● Laat geen overerving toe● Alle velden final● Alle velden private● Geen toegang tot wijzigbare componenten
![Page 20: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/20.jpg)
20
Voorbeeld: Breuken
public class Fraction {
public int numerator; public int denominator; }
![Page 21: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/21.jpg)
21
Breuken: “Bean” patternpublic class Fraction { private int numerator; private int denominator; public Fraction(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; reduce(); }
public int getNumerator() { return numerator; } public int getDenominator() { return denominator; } public void setNumerator(int numerator) { this.numerator = numerator; reduce(); } public void setDenominator(int denominator) { this.denominator = denominator; reduce(); } ...}
![Page 22: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/22.jpg)
22
Breuken: hulpcodeprivate void reduce() { int gcd = gcd(numerator, denominator); numerator /= gcd; denominator /= gcd);}
private static int gcd(int a, int b) { if (b==0) return a; return gcd(b,a%b);}
@Override public String toString() { return "" + getNumerator() + "/" + getDenominator();}
![Page 23: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/23.jpg)
23
Breuken: rekenen
public void add(Fraction that) { numerator = this.getNumerator() * that.getDenominator() + this.getDenominator() * that.getNumerator(); denominator = this.getDenominator() * that.getDenominator(); reduce();} public void multiply(Fraction that) { numerator = this.getNumerator() * that.getNumerator(); denominator = this.getDenominator() * that.getDenominator(); reduce();}
![Page 24: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/24.jpg)
24
Onveranderlijke Breuken
public final class Fraction {
private final int numerator; private final int denominator;
public Fraction(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; }
public int getNumerator() { return numerator; } public int getDenominator() { return denominator; }}
![Page 25: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/25.jpg)
25
Of misschien zelfs
public final class Fraction {
public final int numerator; public final int denominator;
public Fraction(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; }}
![Page 26: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/26.jpg)
26
Terzijde: hetzelfde in Scala ;-)
class Fraction(val numerator: Int, val denominator: Int)
![Page 27: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/27.jpg)
27
Rekenen met onveranderlijke breuken
public Fraction add(Fraction that) { return new Fraction( this.numerator * that.denominator + that.numerator * this.denominator, this.denominator * that.denominator);}
public Fraction multiply(Fraction that) { return new Fraction( this.numerator * that.numerator, this.denominator * that.denominator);}
![Page 28: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/28.jpg)
28
Wijzigbare componentenpublic class Farm { private Field[][] fields; public Farm(int width) { this.fields = new Field[width][width]; initFields(); } private void initFields() { … } public Field[][] getFields() { return fields; }}
Farm farm = new Farm(4);Field[][] fields = farm.getFields();fields[2][3] = null; // zou niet mogen!
![Page 29: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/29.jpg)
29
Wijzigbare componenten
● Geef individuele elementen terug, vb. public Field getField(int row, int col) { return fields[row][col]; }
● Maak een “defensieve kopie”
![Page 30: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/30.jpg)
30
Let op! (EJ#39)public final class Period { private final Date start; private final Date end; public Period(Date start, Date end) { this.start = start; this.end = end; }
public Date getStart() { return start; } public Date getEnd() { return end; }}
![Page 31: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/31.jpg)
31
Aanval op interne toestand Period
Date start = new Date(2012, 06, 01);Date end = new Date(2012, 06, 30);Period p = new Period(start, end);
end.setYear(2013);
// Deze test zal falen!assertEquals(2012, p.getEnd().getYear());
![Page 32: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/32.jpg)
32
Defensieve kopie
public Period(Date start, Date end) { this.start = new Date(start.getTime()); this.end = new Date(end.getTime());}
![Page 33: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/33.jpg)
33
Immutability – voordelen
● Simpel: één toestand● Makkelijker testen● Altijd thread-safe!● Kan je hergebruiken
public static final Fraction ZERO = new Fraction(0,0);public static final Fraction ONE = new Fraction(1,1);
● Kopies maken eigenlijk overbodig● Bouwstenen voor andere objecten
![Page 34: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/34.jpg)
34
Immutability – nadelen
● Veel objecten aanmaken● op te lossen, bv. met static factories (zie verder)
![Page 35: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/35.jpg)
35
Is doorgedreven “immutability”mogelijk / wenselijk?
![Page 36: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/36.jpg)
36
Verkies compositie boven overerving (EJ#16)
● Overerving kan● binnen zelfde package, onder controle van zelfde
programmeurs● van specifiek daarvoor ontworpen klassen● van interfaces
● Overerving vermijden● van “gewone” concrete klassen over packages heen
![Page 37: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/37.jpg)
37
Waarom?
● Overerving breekt encapsulatie● Subklassen hangen af van implementatie superklasse
● Superklasse wijzigen problemen in subklassen● Compilatie● Verkeerd gedrag● Beveiligingsproblemen
● Oplossing: “wrapper class”
![Page 38: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/38.jpg)
38
Verkies interfaces boven abstracte klassen (EJ#18)
● Bestaande klassen kunnen makkelijk aangepast worden om nieuwe interface te implementeren
● Interfaces zijn ideaal voor het definiëren van “mixins” (vgl. Scala Traits, Ruby Modules)
● Interfaces maken niet-hierarchische typeframeworks mogelijk
● Veilige manier om functionaliteit uit te breiden
![Page 39: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/39.jpg)
39
Niet-hierarchische typeframeworks
![Page 40: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/40.jpg)
40
Nadelen
● Geen implementatie● voorzie basisimplementatie (“skeletal”)● kan jouw klasse niet overerven van basisimpl.?
“simulated multiple inheritance”
● Eens een interface gepubliceerd is, kan je niet meer wijzigen
![Page 41: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/41.jpg)
41
Simulated Multiple Inheritance
![Page 42: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/42.jpg)
42
Objecten vs Datastructuren (CC6)
● Objecten● Verbergen data/implementatie achter abstracties● Hebben functies om deze data te bewerken
● Datastructuren● Hebben data● Hebben geen functies van belang
![Page 43: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/43.jpg)
43
Vb: 2 implementaties voor vormen
● Datastructuren/procedureel
public class Square { public Point topLeft; public double side;}public class Circle { public Point center; public double radius;}
![Page 44: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/44.jpg)
44
public class Geometry { public double area(Object shape) { if (shape instanceof Square) { Square s = (Square)shape; return s.side * s.side; } else if(shape instanceof Circle) { Circle c = (Circle) shape; return c.radius * c.radius * Math.PI; } else { throw new IllegalArgumentException( "Not a known shape"); } }}
Jamaar, da's geen OO!
![Page 45: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/45.jpg)
45
Vb: 2 implementaties voor vormen
● Objectgeorienteerd
public interface Shape { public double area();}
public class Square implements Shape { private Point topLeft; private double side; @Override public double area() { return side * side; }}
![Page 46: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/46.jpg)
46
public class Circle implements Shape { private Point center; private double radius; @Override public double area() { return Math.PI * radius * radius; }}
![Page 47: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/47.jpg)
47
Twee soorten refactorings
● Functie toevoegen (bv. perimeter())● Procedureel: enkel Geometry aanpassen
● Shapes en hun “clients” blijven ongewijzigd!● OO: ALLE Shapes aanpassen
● Shape toevoegen (bv. Rectangle)● Procedureel: ALLE functies in Geometry aanpassen● OO: enkel Rectangle-klasse schrijven
![Page 48: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/48.jpg)
48
Is de “procedurele” aanpak uit het vorige voorbeeld soms toelaatbaar/aangewezen?
![Page 49: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/49.jpg)
49
Functies
![Page 50: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/50.jpg)
50
Functies / methods
● CC3 Functions● EJ2 Creating and destroying objects● EJ3 Methods common to all objects● EJ5 Methods
![Page 51: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/51.jpg)
51
Functies mogen maar één ding doenZe moeten dat goed doenZe mogen alleen dat doen
![Page 52: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/52.jpg)
52
Richtlijnen voor functies (CC3)
● Kort! => verstaanbaar● geen geneste controlestructuren● ingewikkelde tests in aparte functie
● Eén niveau van abstractie per functie● Beschrijvende namen
● voor functies en variabelen/parameters
● Leesbaar van boven naar beneden● beginnen met “hoofdfunctie”, daarna hulpfuncties
![Page 53: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/53.jpg)
53
Richtlijnen voor functies (CC3)
● Géén neveneffecten● zwakkere betekenis: één ding doen
public boolean checkPwd(String user, String passwd) { … if(hash.equals(storedHash)) { session.initialize(); return true; }}
● sterkere betekenis: geen data muteren● = basisgedachte functioneel programmeren
● N.B. System.out.println() is een neveneffect
![Page 54: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/54.jpg)
54
Richtlijnen voor functies (CC3)
● “Command/query separation”● ofwel iets doen, ofwel een antwoord geven● niet beide
● Géén “output arguments”● vb. Arrays.fill(boolean[] a, boolean val)
● Exceptions ipv “foutcodes” of null (zie ook EJ#43)
● Don't repeat yourself
![Page 55: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/55.jpg)
55
Functie-argumenten (CC3)
● Aantal:● 0 argumenten is best● 1 argument (monad) is het op één na beste● 2 argumenten (dyad) is al moeilijker te begrijpen● 3 argumenten (triad) is ongeveer het maximum
toelaatbare aantal
● Zie ook EJ#40
![Page 56: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/56.jpg)
56
Functie-argumenten (CC3)
● Geen vlag-argumenten● = booleans die gedrag veranderen● Schrijf 2 functies!
● Lange argumentenlijsten● Gebruik argument-objecten
Circle makeCircle(double x, double y, double radius)Circle makeCircle(Point center, double radius)
● Varargs tellen als één argumentvoid monad(Integer... args)void dyad(String name, Integer... args)
![Page 57: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/57.jpg)
57
Creëren van objecten (EJ2)
● Static factory methods ipv constructors (EJ#1)public static Fraction valueOf(int numerator, int denominator) {
int g = gcd(numerator, denominator); return new Fraction(numerator / g, denominator / g);}
private Fraction(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator;}
![Page 58: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/58.jpg)
58
Voordelen van static factory methods
● Hebben naam, returntype● Creëren niet noodzakelijk een nieuw object
● caching● “instance-controlled” klasse, bv. Boolean● laat toe om te garanderen dat bij immutable klassen
geldt: a.equals(b) als en slechts als a == b
● Kunnen object van subtype teruggeven
![Page 59: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/59.jpg)
59
Nadelen van static factory methods
● Onmogelijk overerven van klassen zonder publieke/protected constructors
● misschien niet echt een nadeel
● niet te onderscheiden van andere static methods● naamgeving: valueOf(), of(), newInstance(),
getInstance()
![Page 60: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/60.jpg)
60
Creëren van objecten (EJ2)
● Builder pattern: voor constructors met● teveel parameters● optionele/default parameters● verschillende parameters van zelfde type
![Page 61: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/61.jpg)
61
Voorbeeld: Boerderij-object aanmaken
public Farm(String farmName, String playerName, double startBudget, int gridWidth) {
this.farmName = farmName; this.playerName = playerName; this.startBudget = startBudget; this.width = width; this.fields = makeEmptyFields();}
![Page 62: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/62.jpg)
62
Builder (binnen Farm)public static class Builder { String farmName = ""; String playerName = ""; double startBudget = 1_000.0; int gridWidth = 4; public Builder withFarmName(String farmName) { this.farmName = farmName; return this; } public Builder withPlayerName(String playerName) { this.playerName = playerName; return this; } public Builder withStartBudget(double budget) { this.startBudget = budget; return this; } public Builder withGridWidth(int gridWidth) { this.gridWidth = gridWidth; return this; } public Farm build() { return new Farm(this); }}
![Page 63: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/63.jpg)
63
Constructorsprivate Farm(String farmName, String playerName, double startBudget, int gridWidth) { this.farmName = farmName; this.playerName = playerName; this.budget = startBudget; this.gridWidth = gridWidth; this.fields = makeEmptyFields();}
private Farm(Builder builder) { this(builder.farmName, builder.playerName, builder.startBudget, builder.gridWidth);}
![Page 64: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/64.jpg)
64
Client code
Farm farm = new Farm.Builder() .withFarmName("Carlokes") .withPlayerName("René") .withStartBudget(1_000.00) .withGridWidth(5) .build();
![Page 65: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/65.jpg)
65
Voordelen van Builders
● Autocomplete helpt bij invullen van parameters● Niet meer onthouden in welke volgorde
parameters komen● Vermijden verschillende ctors voor default-
waarden● Opleggen van invariants bij objectcreatie● Verschillende varargs mogelijk● Makkelijker parameters toevoegen
![Page 66: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/66.jpg)
66
Let op bij implementeren equals() (EJ#8)
● Enkel implementeren wanneer nodig● Typisch voor “waarde-objecten,” bv. Date,
Integer, Fraction● Respecteer het “contract” van equals()
![Page 67: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/67.jpg)
67
equals() is een equivalentierelatie
● Reflexief: x ≠ null: x.equals(x)
● Symmetrisch: x,y ≠ null: x.equals(y) y.equals(x)
● Transitief: x,y,z ≠ null: x.equals(y) en y.equals(z) x.equals(z)
● Consistent: x,y ≠ null: x.equals(y) geeft telkens zelfde waarde terug
● x ≠ null: x.equals(null) geeft altijd false terug
![Page 68: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/68.jpg)
68
Recept voor equals(Object o)
1.Controleer of o referentie naar dit object is● zo ja true
2.Controleer met instanceof of o het correcte type heeft,
● zo niet false● zo ja, casten naar juiste type
3.Controleer of elk “significant” attribuut van o overeenkomt met het corresponderende attribuut van dit object
![Page 69: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/69.jpg)
69
vb. Fraction(gegenereerd door Eclipse!)
@Override public boolean equals(Object obj) { if (this == obj) // 1 return true; if (obj == null) return false; if (getClass() != obj.getClass()) // 2 return false; Fraction other = (Fraction) obj; if (denominator != other.denominator) // 3 return false; if (numerator != other.numerator) return false; return true; }
![Page 70: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/70.jpg)
70
Overschrijf hashCode() als je equals() overschrijft (EJ#9)
● Zoniet overtreed je contract van Object.hashCode()
● vb. x,y ≠ null: x.equals(y) x.hashCode() == y.hashCode()
● Klasse zal niet werken in HashMap, HashSet, Hashtable
● default impl.: verschillend object verschillende hashCodes
![Page 71: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/71.jpg)
71
Recept voor hashCode()
● cfr. boek● gebruik door Eclipse gegenereerde hashCode()
![Page 72: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/72.jpg)
72
vb. Fraction
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + denominator; result = prime * result + numerator; return result; }
![Page 73: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/73.jpg)
73
hashCode voor ingewikkeld immutable object
● “Lazily initialized, cached hashCode”
private volatile int hashCode;
@Override public int hashCode() { if(hashCode == 0) { final int prime = 31; int result = 1; result = prime * result + denominator; result = prime * result + numerator; hashCode = result; } return hashCode;}
![Page 74: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/74.jpg)
74
Altijd toString() overschrijven (EJ#10)
● Klasse makkelijker te gebruikenvb. Fraction: “3/5” ipv “Fraction@163b94”
● Bevat zo mogelijk alle interessante info uit object● Documenteer formaat in javadoc● Alle info in de string is via accessors/publieke
velden te verkrijgen
![Page 75: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/75.jpg)
75
hashCode(), equals() en toString() in Scala ;-)
case class Fraction( val numerator: Int, val denominator: Int)
![Page 76: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/76.jpg)
76
Argumenten controleren (EJ#38)
● “Client-code is de vijand”● Expliciet maken van veronderstellingen over
gebruik van de method● Vermijden van problemen bij geven van
verkeerde/onverwachte input● Sneller fouten opsporen
![Page 77: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/77.jpg)
77
Argumenten controleren (EJ#38)
● Publieke methods:● Gebruik IllegalArgumentException en duidelijke
foutboodschap● Documenteer met Javadoc @throws
● Niet-publieke methods● Gebruik assert● Wordt enkel gecompileerd met optie -ea
![Page 78: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/78.jpg)
78
Schrijf nooit “return null;”
● Client-code verplicht uitzondering te behandelen● “null-checks” vervuilen je code
● Aanleiding tot NullPointerException● Alternatief:
● Exception● “Leeg” object, bv. Collections.emptyList()● Opl. in Scala: Option[T] → Some[T] of None
![Page 79: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/79.jpg)
79
Exceptions
● EJ#60: bij voorkeur standaard-exceptions gebruiken
● EJ#62: alle mogelijke exceptions documenteren met @throws
● EJ#65: niet onder de mat vegen● try { … }catch(SomeException e) {}
● try { … }catch(SomeException e) { e.printStackTrace(); }
![Page 80: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/80.jpg)
80
Checked vs Unchecked Exceptions
● Tegenspraak tussen EJ en CC● EJ#58: Checked exceptions voor uitzonderlijke
condities, runtime exceptions voor bugs● daarvoor zijn ze ontworpen!
● CC7: “The debate is over. Use Unchecked Exceptions.”
● “doorbreken encapsulatie”● ontbreken van checked exceptions staan robuuste
code niet in de weg
![Page 81: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/81.jpg)
81
Checked vs Unchecked Exceptions
● EJ#59. Onnodig gebruik van checked exceptions vermijden
● “lastig” voor gebruiker API● nodigt uit slechte foutafhandeling te schrijven
● EJ#64. Streven naar “atomair falen”● Exception laat object in toestand van vóór method →
call● cfr. ACID bij databases
![Page 82: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/82.jpg)
82
Unit tests
![Page 83: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/83.jpg)
83
3 wetten van Test Driven Development (CC9)
1. Schrijf geen productiecode vóór een mislukkende unit test
2. Schrijf niet meer in een unit test dan voldoende om te falen (niet compileren = falen)
3. Schrijf niet meer productiecode dan voldoende om de falende test te laten slagen
![Page 84: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/84.jpg)
84
Aanbevelingen voor Unit tests
● Hou de test-code “clean”, leesbaar
● testcode is even belangrijk als productiecode
● Domeinspecifieke test-taal
● = “utility methods” die testcode leesbaarder maken
● Eén assert per test
● Niet in steen gebeiteld, maar hou minimaal● → Eén concept per test
● Gebruik code coverage tool & streef naar 100%
● Private method package local maken om te kunnen testen mag!
![Page 85: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/85.jpg)
85
F.I.R.S.T. principe voor Unit Tests
● Fast: je moet tests vaak willen draaien● Independent: “waterval” van problemen
vermijden● Repeatable: in ontwikkelings/QA/UA/productie-
omgevingen● Self-Validating: “wit-zwart”, geen “grijs”● Timely: tijdig schrijven zorgt voor testbare code
![Page 86: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/86.jpg)
86
Ontwerpen
![Page 87: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/87.jpg)
87
“Emergent design” (CC12)
● Een ontwerp is “eenvoudig” als het volgende regels volgt:
● draait alle tests● bevat geen duplicatie● is expressief, drukt de bedoeling van de
programmeur uit● minimaliseert het aantal klassen en functies
● < Kent Beck, “Extreme Programming Explained”
![Page 88: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/88.jpg)
88
“Emergent design”
● Met deze regels “ontstaat” een goed ontwerp “als vanzelf” tijdens het programmeren
● Maakt het makkelijker bv. “Single Responsibility Principle” of “Dependency Inversion Principle” te volgen
![Page 89: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/89.jpg)
89
Alle tests draaien
● Een goed ontwerp produceert een systeem dat zich gedraagt zoals bedoeld was
● Zorgen voor testbare code zorgt voor beter ontwerp
● leidt tot “high cohesion – low coupling”
● Code opkuisen zal functionaliteit niet breken
![Page 90: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/90.jpg)
90
Geen duplicatie
● Makkelijkst: identieke lijnen code● Ook bvb. int size() vs boolean isEmpty()
● met aparte implementatie voor beide
● “Template methods” gebruiken● Wat met identieke implementatie, maar
verschillende intentie?
![Page 91: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/91.jpg)
91
Intentie vs implementatie(RubySlim voorbeeld)
def slim_to_ruby_method(method_name) value = method_name[0..0].downcase + method_name[1..-1] value.gsub(/[A-Z]/) { |cap| "_#{cap.downcase}" }end
def to_file_name(module_name) value = module_name[0..0].downcase + module_name[1..-1] value.gsub(/[A-Z]/) { |cap| "_#{cap.downcase}" }end
● “Slim” methodnaam naar Ruby methodnaam:
● “Slim” packagenaam omzetten naar bestandsnaam
http://www.informit.com/articles/article.aspx?p=1313447
![Page 92: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/92.jpg)
92
Intentie vs implementatie
● Naar elkaar laten verwijzen?● Nee: to_file_name moet niets weten van
methodnamen en v.v.
● Hernoemen naar to_camel_case? ● Nee: client-code moet niets weten van
implementatiedetails
● Aparte method to_camel_case + oorspronkelijke 2 er naar laten verwijzen
● = toepassing één niveau van abstractie
![Page 93: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/93.jpg)
93
Intentie vs implementatie
def slim_to_ruby_method(method_name) camel_to_underscore(method_name)end
def to_file_name(module_name) camel_to_underscore(module_name)end
def camel_to_underscore(camel_namme) value = camel_name[0..0].downcase + camel_name[1..-1] value.gsub(/[A-Z]/) { |cap| "_#{cap.downcase}" }end
![Page 94: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/94.jpg)
94
Expressiviteit
● Maak systeem makkelijk begrijpbaar● code drukt uit wat de programmeur bedoelt
● Goede naamgeving● weergave van verantwoordelijkheden● gestandaardiseerde naamen (bv. patterns)
● Goed geschreven Unit Test● = documentatie a.h.v. voorbeeld
![Page 95: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/95.jpg)
95
Expressiviteit
● Voldoende aandacht besteden hieraan● Niet verder doen met iets anders zodra het “werkt”
● Fierheid over je vakmanschap
![Page 96: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/96.jpg)
96
Minimaal aantal klassen en methods
● Tegenspraak met “kleine klassen”?● kan te ver gedreven worden● mag geen “dogma” zijn (vb. scheiden van data- &
gedrag-klassen)● evenwicht
● Tests, elimineren duplicatie, expressiviteit zijn belangrijker
![Page 97: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/97.jpg)
97
Stijl
![Page 98: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/98.jpg)
98
Commentaar (CC4)
● Commentaar is geen oplossing voor slechte code● Druk je intentie uit in code
![Page 99: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/99.jpg)
99
Goede commentaar
● Wettelijke bepalingen (vb. licentie, copyrigth)● Informatieve commentaar
● functienaam zegt het al!● bv. wél uitleg bij ingewikkelde regexp
// Returns the numerator of this Fraction.public int getNumerator() { return numerator;}
![Page 100: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/100.jpg)
100
Goede commentaar
● Intentie uitleggen● Verduidelijking
● vb. betekenis argument/return-waarde● kan best op andere manier in je eigen code● bij API-calls geen keuze
● Waarschuwing consequenties● bv. test die lang duurt
![Page 101: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/101.jpg)
101
Goede commentaar
● TODO● worden bijgehouden in Eclipse, Netbeans
● Javadoc publieke API (cfr. EJ#44)● Let op, Javadocs kunnen even misleidend zijn dan
andere (slechte) commentaar● Is dit goede commentaar?
/** Returns the denominator of this Fraction. * @return the denominator of this Fraction. */public int getDenominator() { return denominator; }
![Page 102: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/102.jpg)
102
Slechte commentaar
● “Gebrabbel”● Redundante commentaar
● zegt hetzelfde als de code (maar dan minder precies)● legt niets uit over intentie code
● Misleidende commentaar● te vaag om te kloppen
● Verplichte commentaar● vb. Javadoc van triviale methods
![Page 103: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/103.jpg)
103
Slechte commentaar
● “Log” van wijzigingen● is werk voor versiebeheersysteem!
● Commentaar als vervanging van goede variabele-/methodnaam
● Positiemarkeringen//---------- Accessors --------------------------
● Commentaar bij sluiten accolade
![Page 104: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/104.jpg)
104
Slechte commentaar
● Vermeldingen auteurs● Hoort in versiebeheersysteem
● Code in commentaar● Vervuilt de code● Wat is de intentie? Waarom in commentaar?● Versiebeheer!
● HTML commentaar
![Page 105: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/105.jpg)
105
Slechte commentaar
● Niet-lokale informatie● Teveel informatie● Onduidelijke link met code● Functie-headers● Javadocs in niet-publieke code
![Page 106: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/106.jpg)
106
Naamgeving (CC2)
● Namen geven intentie bloot● int d; // elapsed time in days
● Vermijd desinformatie● private Person[] personList;● kleine L (l of 1?), hoofletter O (O of 0?)
● Namen zijn uitspreekbaar
![Page 107: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/107.jpg)
107
Naamgeving
● Zinvol onderscheid tussen namen● variabele niet verkeerd spellen om onderscheid te
maken met andere, vb. class klass↔● geen getalseries, vb. a1, a2, a3, …● redundante namen, vb. denominatorVariable
● Namen zijn zoekbaar● hoe breder de scope, hoe langer de naam● variabelen met 1 letter enkel lokaal in korte methods
![Page 108: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/108.jpg)
108
Naamgeving
● Vermijd “coderingen”● “Hongaarse notatie” met type in de naam, vb.
phoneString● “Member prefix” voor onderscheid met functie-
argumenten, vb. private int mNumerator;● Interface prefix, vb. IShapeFactory
● Probeer niet grappig te zijn
![Page 109: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/109.jpg)
109
Naamgeving
● Consistent: één woord per concept● fetch retrieve get↔ ↔● Controller Manager Driver↔ ↔
● Namen uit oplossingsdomein (vakjargon, patterns, wiskundige termen, …)
● Namen uit probleemdomein
![Page 110: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/110.jpg)
110
Naamgeving
● Klassenamen● gebaseerd op zelfstandige naamwoorden, vb.
Customer, WikiPage, AddressParser● vermijd te algemene woorden als Manager,
Processor, Data, Info, Controller● geen werkwoord
![Page 111: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/111.jpg)
111
Naamgeving
● Methodnamen● gebaseerd op werkwoorden● accessors/mutators beginnen met get/set● predicaten beginnen met is● constructor overloading factory methods die →
argument beschrijven● vb. Complex(double) →Complex.fromRealNumber(double)
![Page 112: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/112.jpg)
112
En verder...
![Page 113: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/113.jpg)
113
Waarom de boeken nog lezen/kopen?
● Verschillende topics niet aan bod gekomen● Concurrency (CC13 & appendix A, EJ10)● Praktijkvoorbeelden refactoring (CC14, CC16)● “Smells and Heuristics” (CC17)
![Page 114: Clean, effective java](https://reader038.vdocuments.net/reader038/viewer/2022110114/547e37deb4af9f87478b47ce/html5/thumbnails/114.jpg)
114
Bedankt!