Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Gute Zeilen, schlechte ZeilenRegeln für wartbare Programme       Dirk Weil | GEDOPLAN
Dirk Weil    • GEDOPLAN GmbH, Bielefeld    • Java EE seit 1998    • Konzeption und      Realisierung    • Vorträge    • Se...
GUTE           ZEILEN           SCHLECHTE           ZEILEN3   Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Gibt es guten und schlechten Code?    • Software ist (fast) nie fertig    • Software wird (meist) im Team entwickelt    • ...
Gibt es guten und schlechten Code?    • Entwicklerteams sind meist heterogen      – Berufserfahrung      – Programmierstil...
Richtlinien    Low Level: Namen, Formatierung …      Grundlegendes Klassendesign            Code-Komplexität          Anwe...
Statische Code-Analyse    • Matching des Codes gegen Regelsätze    • Einfache (Text-)Pattern … strukturelle Pattern       ...
Dokumentation    • Javadoc für API      – Klassen, Interfaces,        Methoden, Variablen      – public, protected      – ...
Dokumentation    • API-Dokumentation veröffentlichen      – Source-Jars                <plugin>        erzeugen,          ...
Dokumentation     • Erklärungsbedürftige Codesequenzen       /*        * Fahrstrassen innerhalb von Fahrstrassen expandier...
Namen     • Klassen, Variablen, Methoden entsprechend ihrer       Aufgabe benennen       – spart umfangreiche Dokumentatio...
Namen     • Keine Präfixnotation für Typen, Sichtbarkeit etc.:        Instanzvariable                                   Na...
Namen     • CS kann Namenskonventionen prüfen       (Module group Naming Conventions)     • IDE-Komfort nutzen!       – Qu...
Formatierung     • Code sollte im Team einheitlich formatiert sein       – Einrückung (Tab/Blanks, wie viele?)       – Pla...
equals, hashCode     • equals definieren   hashCode definieren     • nicht nur equals(MyType)     • Codeanalyse:       – C...
equals, hashCode      • Jedes Geschäftsobjekt sollte equals und        hashCode definieren      • IDEs bieten gute Unterst...
switch     • Regeln:       – default nicht vergessen       – kein Fall Through     • CS: Missing Switch Default, Fall Thro...
Protokollierung     • keine Protokollausgabe auf stdout, stderr     • "Mal schnell ne Ausgabe"     • Achtung: IDE-Template...
Exception-Verwendung     • Werfen und Fangen von Throwable,       Exception, RuntimeException i. A. fehlerhaft     • CS: I...
DRY     • Keine Copy&Paste-Programmierung     • CS: Strict Duplicate Code       (nicht wirklich empfehlenswert)20         ...
Komplexität     • Klassen / Methoden nicht zu lang     • Anzahl Methodenparameter nicht zu groß     • CS: Maximum Method L...
Einfach machen     • Einfache Lösungen sind gute Lösungen     • Vorsicht bei:       – Reflection          • extrem schlech...
Einfach machen     • Anschauungsbeispiel: Entity Editor       – Generischer Editor für Geschäftsobjekte       – Steuerung ...
Klassen sparen lohnt nicht     • Anschauungsbeispiel "Wachdienst":       – Gebäudekontrolle durch Prüfung aller Räume     ...
Klassen sparen lohnt nicht     • Anschauungsbeispiel "Wachdienst"       – 1. Ansatz: Keine Klasse für Etage       – Dialog...
Klassen sparen lohnt nicht     • Anschauungsbeispiel "Wachdienst"       – Besser: Zusätzliche Ebene für Etagen       – Kla...
Wohin mit der Logik?27     Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Wohin mit der Logik?     • Anschauungsbeispiel "Modellbahnsteuerung":       – Reservieren einer Fahrstraße         = Stell...
Wohin mit der Logik?     • Anschauungsbeispiel "Modellbahnsteuerung":       – 1. Ansatz: Iteration über Fahrstraßenelement...
Wohin mit der Logik?      • Anschauungsbeispiel "Modellbahnsteuerung":           – Besser:               • Platzierung der...
Wohin mit der Logik?     • Geschäftslogik in Geschäftslogik-Schicht       – CDI, EJB, JPA, …     • Präsentationslogik bspw...
In Objekten denken      • Anschauungsbeispiel: 1:n-Relation (JPA)                                         @Entity         ...
Packages     • Zwei Anti-Beispiele33                 Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Anekdoten     String name = new String();     name = "Hugo";         if (val != null && ("" + val.getClass().getName()).eq...
Anekdoten     public void changeRichtung()     {       if (isRueckwaerts())         setRueckwaerts(false);       else     ...
Anekdoten     @POST     @Path("artikel/{artNr}/menge")     public Response setSpeed(@PathParam("artNr") String adrNr,     ...
Anekdoten     if (this.kommPunkt.isTurnText())     {       g2.setFont(system.getKommPunktFont());       g2.translate(kommP...
Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Nächste SlideShare
Wird geladen in …5
×

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

1.548 Aufrufe

Veröffentlicht am

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

  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

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

  1. 1. Gute Zeilen, schlechte ZeilenRegeln für wartbare Programme Dirk Weil | GEDOPLAN
  2. 2. Dirk Weil • GEDOPLAN GmbH, Bielefeld • Java EE seit 1998 • Konzeption und Realisierung • Vorträge • Seminare • Veröffentlichungen2 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  3. 3. GUTE ZEILEN SCHLECHTE ZEILEN3 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  4. 4. Gibt es guten und schlechten Code? • Software ist (fast) nie fertig • Software wird (meist) im Team entwickelt • Teams ändern sich über die Zeit • Software muss verständlich sein4 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  5. 5. Gibt es guten und schlechten Code? • Entwicklerteams sind meist heterogen – Berufserfahrung – Programmierstil –… • Richtlinien helfen – bei der Einarbeitung in fremde Software – bei der (Weiter-) Entwicklung5 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  6. 6. Richtlinien Low Level: Namen, Formatierung … Grundlegendes Klassendesign Code-Komplexität Anwendungsstruktur6 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  7. 7. Statische Code-Analyse • Matching des Codes gegen Regelsätze • Einfache (Text-)Pattern … strukturelle Pattern Checkstyle7 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  8. 8. Dokumentation • Javadoc für API – Klassen, Interfaces, Methoden, Variablen – public, protected – Kontrolle bspw. per Checkstyle Javadoc Comments • Prüft per Default auch private scope = protected • Getter/Setter-Doku meist überflüssig allowMissingPropertyJavadoc = true8 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  9. 9. Dokumentation • API-Dokumentation veröffentlichen – Source-Jars <plugin> erzeugen, <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> z. B. mit Maven <inherited>true</inherited> <executions> <execution> <id>attach-sources</id> – ermöglicht Unter- <phase>verify</phase> <goals> stützung durch <goal>jar-no-fork</goal> </goals> die IDE </execution> </executions> </plugin>9 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  10. 10. 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; while (true) { for (Fahrstrasse fahrstrasse : this.fahrstrassen) … • Trivialdokumentation ist überflüssig // Neue Weichenstellung protokollieren this.logger.trace(this + ": setStellung(" + stellung + ")");10 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  11. 11. Namen • Klassen, Variablen, Methoden entsprechend ihrer Aufgabe benennen – spart umfangreiche Dokumentation • Well-Known Names nicht umdeuten! • Anschauungsbeispiel: "Nothalt-Funktion" public void setAnlagenstatus() { Anlagenstatus.getInstance().changeAnlagenstatus(); – Anlagenstatus ist zu generell – Methode setzt den Status nicht, sondern toggelt – setXyz ist well-known mit anderer Bedeutung11 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  12. 12. 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 … … – 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 zweitrangig12 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  13. 13. 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 –…13 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  14. 14. Formatierung • Code sollte im Team einheitlich formatiert sein – Einrückung (Tab/Blanks, wie viele?) – Platzierung von { – Zeilenumbruch –… • Vorteile – Code liest sich leichter – kleinere Change Sets im SCM • Lässt sich mit IDE-Komfort leicht erreichen – Save action: Format code14 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  15. 15. equals, hashCode • equals definieren hashCode definieren • nicht nur equals(MyType) • Codeanalyse: – CS: Equals and Hashcode, Covariant Equals , – FB: Class defines equals and uses Object.hashCode15 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  16. 16. equals, hashCode • Jedes Geschäftsobjekt sollte equals und hashCode definieren • IDEs bieten gute Unterstützung • Achtung bei equals in Basisklassen 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 { …16 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  17. 17. switch • Regeln: – default nicht vergessen – kein Fall Through • CS: Missing Switch Default, Fall Through17 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  18. 18. Protokollierung • keine Protokollausgabe auf stdout, stderr • "Mal schnell ne Ausgabe" • Achtung: IDE-Templates! • CS: Regexp… mit passendem Pattern18 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  19. 19. Exception-Verwendung • Werfen und Fangen von Throwable, Exception, RuntimeException i. A. fehlerhaft • CS: Illegal Catch, Illegal Throws19 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  20. 20. DRY • Keine Copy&Paste-Programmierung • CS: Strict Duplicate Code (nicht wirklich empfehlenswert)20 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  21. 21. Komplexität • Klassen / Methoden nicht zu lang • Anzahl Methodenparameter nicht zu groß • CS: Maximum Method Length, Maximum Parameters, Maximum File Length, Cyclomatic Complexity (Anwendung im Team diskutieren!)21 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  22. 22. Einfach machen • Einfache Lösungen sind gute Lösungen • Vorsicht bei: – Reflection • extrem schlecht lesbar • Refactoring problematisch – hochgradig konfigurierbaren Klassen • schwer nutzbar (bspw. GridBagConstraints) – übermäßigem Einsatz von Typparametern22 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  23. 23. Einfach machen • Anschauungsbeispiel: Entity Editor – Generischer Editor für Geschäftsobjekte – Steuerung per Annotation @Editable – Remote funktionsfähig ( kein EntityManager) • Hochgradige Nutzung von Reflection • Umfangreiche Konfiguration von Services etc. • Einsatzfall BDE-System – ca. 35 Entities23 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  24. 24. Klassen sparen lohnt nicht • Anschauungsbeispiel "Wachdienst": – Gebäudekontrolle durch Prüfung aller Räume – Räume sind auf Etagen verteilt – Kontrollierte Räume werden abgehakt24 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  25. 25. Klassen sparen lohnt nicht • Anschauungsbeispiel "Wachdienst" – 1. Ansatz: Keine Klasse für Etage – Dialogaufbau unnötig kompliziert (~ Gruppenwechsel) – Kein Platz für zukünftige Erweiterung um Etagen-Daten25 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  26. 26. Klassen sparen lohnt nicht • Anschauungsbeispiel "Wachdienst" – Besser: Zusätzliche Ebene für Etagen – Klares Konzept Real World Klasse26 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  27. 27. Wohin mit der Logik?27 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  28. 28. Wohin mit der Logik? • Anschauungsbeispiel "Modellbahnsteuerung": – Reservieren einer Fahrstraße = Stellen der betroffenen Weichen und Signale – Fahrstrasse liegt als Geschäftsobjekt vor – Anforderung als Webservice28 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  29. 29. Wohin mit der Logik? • Anschauungsbeispiel "Modellbahnsteuerung": – 1. Ansatz: Iteration über Fahrstraßenelemente im Webservice @POST @Path("/fahrstrasse/{bereich}/{name}/reserviert") public Response setFahrstrassenreservierung(...) { – Nachteile: Fahrstrasse fahrstrasse = … for (FahrstrassenElement fe • nicht wieder- : fahrstrasse.getElemente()) verwendbar, da { Fahrwegelement fwe = fe.getFahrwegelement(); im Webservice if (fwe instanceof Weiche) • "Polymorphie { Weiche w = (Weiche) fwe; für Arme" w.setStellung(…); } …29 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  30. 30. Wohin mit der Logik? • Anschauungsbeispiel "Modellbahnsteuerung": – Besser: • Platzierung der Logik in Fahrstrasse • Abstrakte Methode statt expliziter Typabfrage @Path("{bereich}/{name}/reserviert") @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);30 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  31. 31. 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. • Saubere Schichtung – erhöht Wiederverwendbarkeit – macht den Code übersichtlicher31 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  32. 32. In Objekten denken • Anschauungsbeispiel: 1:n-Relation (JPA) @Entity public class Book { @Entity @Id @GeneratedValue Integer id; public class Publisher @ManyToOne Publisher publisher; { @Id @GeneratedValue Integer id; @OneToMany(mappedBy = "publisher") List<Book> books; … – Query "Suche Books eines Publishers" (Warum so kompliziert?): Publisher publisher = …; … em.createQuery("select b from Book b where b.publisher.id=:publisherId", Book.class) .setParameter("publisherId", publisher.getId()) .getResultList();32 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  33. 33. Packages • Zwei Anti-Beispiele33 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  34. 34. Anekdoten String name = new String(); name = "Hugo"; if (val != null && ("" + val.getClass().getName()).equals("java.lang.String")) Set<String> texte = …; Set<Object> labels = new TreeSet<>(); labels.addAll(texte); int adr = …; String adrAsString = new Integer(adr).toString();34 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  35. 35. Anekdoten public void changeRichtung() { if (isRueckwaerts()) setRueckwaerts(false); else setRueckwaerts(true); } public class Anlagenstatus { private static Anlagenstatus anlagenstatus = null; private Anlagenstatus() { } public static Anlagenstatus getInstance() { if (anlagenstatus == null) anlagenstatus = new Anlagenstatus(); return anlagenstatus; }35 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  36. 36. Anekdoten @POST @Path("artikel/{artNr}/menge") public Response setSpeed(@PathParam("artNr") String adrNr, @FormParam("menge") String menge) { try { int mengeInt = Integer.parseInt(menge); … } catch (NumberFormatException e) { Auto car1 = ...; Auto car2 = ...; if (car1.getId().getValue().equals(car2.getId().getValue())) { ...36 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  37. 37. Anekdoten if (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); } 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); }37 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  38. 38. Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de

×