38
Gute Zeilen, schlechte Zeilen Regeln für wartbare Programme Dirk Weil | GEDOPLAN

Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

  • Upload
    javatim

  • View
    1.157

  • Download
    0

Embed Size (px)

DESCRIPTION

Gute zeilen, schlechte Zeilen - Vortrag Dirk Weil auf der JAX 2012. IPS Stand JAX 2012.

Citation preview

Page 1: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Gute Zeilen, schlechte ZeilenRegeln für wartbare Programme

Dirk Weil | GEDOPLAN

Page 2: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Dirk Weil• GEDOPLAN GmbH, Bielefeld• Java EE seit 1998• Konzeption und

Realisierung• Vorträge

[email protected]

• Vorträge• Seminare• Veröffentlichungen

2 Gute Zeilen, schlechte Zeilen

Page 3: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

GUTEZEILEN

[email protected] Gute Zeilen, schlechte Zeilen

SCHLECHTE

ZEILEN

ZEILEN

Page 4: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Gibt es guten und schlechten Code?• Software ist (fast) nie fertig• Software wird (meist) im Team entwickelt• Teams ändern sich über die Zeit

[email protected]

• Software muss verständlich sein

Gute Zeilen, schlechte Zeilen4

Page 5: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Gibt es guten und schlechten Code?• Entwicklerteams sind meist heterogen

– Berufserfahrung– Programmierstil– …

• Richtlinien helfen

[email protected]

• Richtlinien helfen– bei der Einarbeitung in fremde Software– bei der (Weiter-) Entwicklung

Gute Zeilen, schlechte Zeilen5

Page 6: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Richtlinien

Low Level: Namen, Formatierung …

Grundlegendes Klassendesign

[email protected]

Code-Komplexität

Anwendungsstruktur

6 Gute Zeilen, schlechte Zeilen

Page 7: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Statische Code-Analyse• Matching des Codes gegen Regelsätze• Einfache (Text-)Pattern … strukturelle Pattern

[email protected] Zeilen, schlechte Zeilen7

Checkstyle

Page 8: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Dokumentation• Javadoc für API

– Klassen, Interfaces,Methoden, Variablen

– public , protected

[email protected]

– Kontrolle bspw. per CheckstyleJavadoc Comments

• Prüft per Default auch private� scope = protected

• Getter/Setter-Doku meist überflüssig� allowMissingPropertyJavadoc = true

Gute Zeilen, schlechte Zeilen8

Page 9: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Dokumentation• API-Dokumentation veröffentlichen

– Source-Jarserzeugen,z. B. mit Maven

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-source-plugin</artifactId>

<inherited>true</inherited>

<executions>

<execution>

<id>attach-sources</id>

[email protected]

– ermöglicht Unter-stützung durchdie IDE

Gute Zeilen, schlechte Zeilen9

<id>attach-sources</id>

<phase>verify</phase>

<goals>

<goal>jar-no-fork</goal>

</goals>

</execution>

</executions>

</plugin>

Page 10: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Dokumentation• Erklärungsbedürftige Codesequenzen

/*

* Fahrstrassen innerhalb von Fahrstrassen expandieren, d. h. durch ihre Elemente

* ersetzen. Dies geschieht in einer Schleife solange, bis alle Expansionen

* erledigt sind oder kein Fortschritt mehr erzielt wird.

*/

int letzteAnzahlFahrstrassenFahrstrassen = 0;

int anzahlFahrstrassenFahrstrassen = 0;

[email protected]

• Trivialdokumentation ist überflüssig

Gute Zeilen, schlechte Zeilen10

int anzahlFahrstrassenFahrstrassen = 0;

while (true)

{

for (Fahrstrasse fahrstrasse : this.fahrstrassen)

// Neue Weichenstellung protokollieren

this.logger.trace(this + ": setStellung(" + stellung + ")");

Page 11: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Namen• Klassen, Variablen, Methoden entsprechend ihrer

Aufgabe benennen– spart umfangreiche Dokumentation

• Well-Known Names nicht umdeuten!• Anschauungsbeispiel: "Nothalt-Funktion"

[email protected]

• Anschauungsbeispiel: "Nothalt-Funktion"

– Anlagenstatus ist zu generell

– Methode setzt den Status nicht, sondern toggelt– setXyz ist well-known mit anderer Bedeutung

Gute Zeilen, schlechte Zeilen11

public void setAnlagenstatus()

{

Anlagenstatus.getInstance().changeAnlagenstatus();

Page 12: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Namen• Keine Präfixnotation für Typen, Sichtbarkeit etc.:

Instanzvariable Name beginnt mit m_

Variable vom Typ List<Integer> Name beginnt mit lI_

Interface Name beginnt mit I

… …

[email protected]

– Präfixnamen tendieren zur Unlesbarkeit(was wäre wohl der Präfix für Map<String, Lok> ?)

– werden durch IDE-Unterstützung mehr als ersetzt

– this. ist aussagekräftiger (OO) als m_

– Unterscheidung Klasse vs. Interface zweitrangig

Gute Zeilen, schlechte Zeilen12

Page 13: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Namen• CS kann Namenskonventionen prüfen

(Module group Naming Conventions )

• IDE-Komfort nutzen!– Quick fix: Namensvorschläge (Variablen, Konstanten ..)– Save actions: Member mit this . qualifizieren

[email protected]

– Save actions: Member mit this . qualifizieren

– …

Gute Zeilen, schlechte Zeilen13

Page 14: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Formatierung• Code sollte im Team einheitlich formatiert sein

– Einrückung (Tab/Blanks, wie viele?)– Platzierung von {

– Zeilenumbruch– …

[email protected]

– …

• Vorteile– Code liest sich leichter– kleinere Change Sets im SCM

• Lässt sich mit IDE-Komfort leicht erreichen– Save action: Format code

Gute Zeilen, schlechte Zeilen14

Page 15: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

equals , hashCode

• equals definieren � hashCode definieren• nicht nur equals (MyType )

• Codeanalyse:– CS: ,

[email protected]

– CS: Equals and Hashcode , Covariant Equals

– FB: Class defines equals and uses Object.hashCode

Gute Zeilen, schlechte Zeilen15

Page 16: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

equals , hashCode

• Jedes Geschäftsobjekt sollte equals und hashCode definieren

• IDEs bieten gute Unterstützung• Achtung bei equals in Basisklassen

public class BadEquals

[email protected] Zeilen, schlechte Zeilen16

public class BadEquals

{

public boolean equals(Object obj)

{

if (getClass() != obj.getClass())

// if (!(obj instanceof BadEquals)) // unsymmetrisch, wenn Subklasse überschreibt

// if (obj.getClass() != BadEquals.class) // funktioniert nicht für Subklassen

{

Page 17: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

switch

• Regeln:– default nicht vergessen

– kein Fall Through

• CS: Missing Switch Default, Fall Through

[email protected] Gute Zeilen, schlechte Zeilen

Page 18: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Protokollierung• keine Protokollausgabe auf stdout , stderr

• "Mal schnell 'ne Ausgabe"• Achtung: IDE-Templates!• CS: Regexp …mit passendem Pattern

[email protected] Gute Zeilen, schlechte Zeilen

Page 19: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Exception-Verwendung• Werfen und Fangen von Throwable ,

Exception , RuntimeException i. A. fehlerhaft

• CS: Illegal Catch , Illegal Throws

[email protected] Gute Zeilen, schlechte Zeilen

Page 20: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

DRY• Keine Copy&Paste-Programmierung

• CS: Strict Duplicate Code(nicht wirklich empfehlenswert)

[email protected] Gute Zeilen, schlechte Zeilen

Page 21: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Komplexität• Klassen / Methoden nicht zu lang• Anzahl Methodenparameter nicht zu groß• CS: Maximum Method Length , Maximum

Parameters , Maximum File Length , Cyclomatic Complexity

[email protected]

Cyclomatic Complexity(Anwendung imTeam diskutieren!)

Gute Zeilen, schlechte Zeilen21

Page 22: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Einfach machen• Einfache Lösungen sind gute Lösungen• Vorsicht bei:

– Reflection• extrem schlecht lesbar• Refactoring problematisch

[email protected]

• Refactoring problematisch

– hochgradig konfigurierbaren Klassen• schwer nutzbar (bspw. GridBagConstraints )

– übermäßigem Einsatz von Typparametern

Gute Zeilen, schlechte Zeilen22

Page 23: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Einfach machen• Anschauungsbeispiel: Entity Editor

– Generischer Editor für Geschäftsobjekte– Steuerung per Annotation @Editable– Remote funktionsfähig (� kein EntityManager)

[email protected]

• Hochgradige Nutzung von Reflection• Umfangreiche Konfiguration von Services etc.

• Einsatzfall BDE-System– ca. 35 Entities

Gute Zeilen, schlechte Zeilen23

Page 24: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Klassen sparen lohnt nicht• Anschauungsbeispiel "Wachdienst":

– Gebäudekontrolle durch Prüfung aller Räume– Räume sind auf Etagen verteilt– Kontrollierte Räume

werden abgehakt

[email protected]

werden abgehakt

Gute Zeilen, schlechte Zeilen24

Page 25: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Klassen sparen lohnt nicht• Anschauungsbeispiel "Wachdienst"

– 1. Ansatz: Keine Klasse für Etage

– Dialogaufbau unnötig kompliziert(~ Gruppenwechsel)

[email protected]

(~ Gruppenwechsel)– Kein Platz für zukünftige Erweiterung

um Etagen-Daten

Gute Zeilen, schlechte Zeilen25

Page 26: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Klassen sparen lohnt nicht• Anschauungsbeispiel "Wachdienst"

– Besser: Zusätzliche Ebene für Etagen

– Klares KonzeptReal World � Klasse

[email protected]

Real World � Klasse

Gute Zeilen, schlechte Zeilen26

Page 27: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Wohin mit der Logik?

[email protected] Zeilen, schlechte Zeilen27

Page 28: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Wohin mit der Logik?• Anschauungsbeispiel "Modellbahnsteuerung":

– Reservieren einer Fahrstraße= Stellen der betroffenen

Weichen und Signale– Fahrstrasse liegt als

[email protected]

Geschäftsobjekt vor

– Anforderung als Webservice

28 Gute Zeilen, schlechte Zeilen

Page 29: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Wohin mit der Logik?• Anschauungsbeispiel "Modellbahnsteuerung":

– 1. Ansatz: Iteration über Fahrstraßenelemente im Webservice

– Nachteile:

@POST

@Path("/fahrstrasse/{bereich}/{name}/reserviert")

public Response setFahrstrassenreservierung(...)

{

Fahrstrasse fahrstrasse = …

[email protected]

– Nachteile:• nicht wieder-

verwendbar, daim Webservice

• "Polymorphiefür Arme"

Gute Zeilen, schlechte Zeilen29

Fahrstrasse fahrstrasse = …

for (FahrstrassenElement fe

: fahrstrasse.getElemente())

{

Fahrwegelement fwe = fe.getFahrwegelement();

if (fwe instanceof Weiche)

{

Weiche w = (Weiche) fwe;

w.setStellung(…);

}

Page 30: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Wohin mit der Logik?• Anschauungsbeispiel "Modellbahnsteuerung":

– Besser:• Platzierung der Logik in Fahrstrasse• Abstrakte Methode statt expliziter Typabfrage

@Path("{bereich}/{name}/reserviert")

@POST

[email protected] Zeilen, schlechte Zeilen30

@POST

public Response setReserviert(…)

{

Fahrstrasse fahrstrasse = …

fahrstrasse.setReserviert(reserviert);

}

public void setReserviert(boolean reserviert)

{

for (FahrstrassenElement element : this.elemente)

element.setReserviert(reserviert);

public abstract void setReserviert(boolean reserviert);

Page 31: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Wohin mit der Logik?• Geschäftslogik in Geschäftslogik-Schicht

– CDI, EJB, JPA, …

• Präsentationslogik bspw. in JSF-Beans– CDI-Models, Managed Beans

• Boundary-Code in EJBs, Webservices etc.

[email protected]

• Boundary-Code in EJBs, Webservices etc.

• Saubere Schichtung– erhöht Wiederverwendbarkeit– macht den Code übersichtlicher

Gute Zeilen, schlechte Zeilen31

Page 32: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

In Objekten denken• Anschauungsbeispiel: 1:n-Relation (JPA)

@Entity

public class Publisher

{

@Id @GeneratedValue Integer id;

@OneToMany(mappedBy = "publisher") List<Book> books;

@Entity

public class Book

{

@Id @GeneratedValue Integer id;

@ManyToOne Publisher publisher;

[email protected]

– Query "Suche Books eines Publishers"(Warum so kompliziert?):

Gute Zeilen, schlechte Zeilen32

@OneToMany(mappedBy = "publisher") List<Book> books;

Publisher publisher = …;

… em.createQuery("select b from Book b where b.publisher.id=:publisherId", Book.class)

.setParameter("publisherId", publisher.getId())

.getResultList();

Page 33: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Packages• Zwei Anti-Beispiele

[email protected] Zeilen, schlechte Zeilen33

Page 34: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Anekdoten

String name = new String();

name = "Hugo";

if (val != null && ("" + val.getClass().getName()).equals("java.lang.String"))

Set<String> texte = …;

[email protected] Zeilen, schlechte Zeilen34

Set<String> texte = …;

Set<Object> labels = new TreeSet<>();

labels.addAll(texte);

int adr = …;

String adrAsString = new Integer(adr).toString();

Page 35: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Anekdoten

public void changeRichtung()

{

if (isRueckwaerts())

setRueckwaerts(false);

else

setRueckwaerts(true);

}public class Anlagenstatus

[email protected] Zeilen, schlechte Zeilen35

public class Anlagenstatus

{

private static Anlagenstatus anlagenstatus = null;

private Anlagenstatus() { }

public static Anlagenstatus getInstance()

{

if (anlagenstatus == null)

anlagenstatus = new Anlagenstatus();

return anlagenstatus;

}

Page 36: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Anekdoten@POST

@Path("artikel/{artNr}/menge")

public Response setSpeed(@PathParam("artNr") String adrNr,

@FormParam("menge") String menge)

{

try

{

int mengeInt = Integer.parseInt(menge);

}

[email protected] Zeilen, schlechte Zeilen36

}

catch (NumberFormatException e)

{

Auto car1 = ...;

Auto car2 = ...;

if (car1.getId().getValue().equals(car2.getId().getValue()))

{

...

Page 37: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

Anekdotenif (this.kommPunkt.isTurnText())

{

g2.setFont(system.getKommPunktFont());

g2.translate(kommPunktBreite / 2 + 2, 0 * kommPunktBreite / 2 - 1);

g2.rotate(Math.toRadians(this.kommPunkt.getDisplayWinkel() - 90),

this.kommPunkt.getDisplayX(), this.kommPunkt.getDisplayY());

g2.setColor(system.getColor(system.PROPERTY_KOMMPUNKT_TEXT_COLOR));

g2.drawString(this.kommPunkt.getId().getValue(), this.kommPunkt.getDisplayX() - 3,

this.kommPunkt.getDisplayY() + 2);

g2.setTransform(this.father.baseTransform);

[email protected] Zeilen, schlechte Zeilen37

g2.setTransform(this.father.baseTransform);

}

else

{

g2.setFont(system.getKommPunktFont());

g2.translate(kommPunktBreite / 2 + 2, 0 * kommPunktBreite / 2 - 1);

g2.rotate(Math.toRadians(this.kommPunkt.getDisplayWinkel() - 90),

this.kommPunkt.getDisplayX(), this.kommPunkt.getDisplayY());

g2.setColor(system.getColor(system.PROPERTY_KOMMPUNKT_TEXT_COLOR));

g2.drawString(this.kommPunkt.getId().getValue(), this.kommPunkt.getDisplayX() - 24,

this.kommPunkt.getDisplayY() + 2);

g2.setTransform(this.father.baseTransform);

}

Page 38: Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012

[email protected] Zeilen, schlechte Zeilen