SlideShare ist ein Scribd-Unternehmen logo
1 von 38
Downloaden Sie, um offline zu lesen
Gute Zeilen, schlechte Zeilen
Regeln für wartbare Programme
       Dirk Weil | GEDOPLAN
Dirk Weil
    • GEDOPLAN GmbH, Bielefeld
    • Java EE seit 1998
    • Konzeption und
      Realisierung
    • Vorträge
    • Seminare
    • Veröffentlichungen




2               Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
GUTE
           ZEILEN
           SCHLECHTE
           ZEILEN

3   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
    • Teams ändern sich über die Zeit

    • Software muss verständlich sein




4                 Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Gibt es guten und schlechten Code?
    • Entwicklerteams sind meist heterogen
      – Berufserfahrung
      – Programmierstil
      –…
    • Richtlinien helfen
      – bei der Einarbeitung in fremde Software
      – bei der (Weiter-) Entwicklung




5                  Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Richtlinien

    Low Level: Namen, Formatierung …


      Grundlegendes Klassendesign


            Code-Komplexität


          Anwendungsstruktur



6            Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Statische Code-Analyse
    • Matching des Codes gegen Regelsätze
    • Einfache (Text-)Pattern … strukturelle Pattern




                                                   Checkstyle




7                  Gute Zeilen, schlechte Zeilen                dirk.weil@gedoplan.de
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 = true



8                    Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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
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
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 Bedeutung


11                   Gute Zeilen, schlechte Zeilen                  dirk.weil@gedoplan.de
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 zweitrangig
12                        Gute Zeilen, schlechte Zeilen                          dirk.weil@gedoplan.de
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
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 code


14                  Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
equals, hashCode
     • equals definieren   hashCode definieren
     • nicht nur equals(MyType)

     • Codeanalyse:
       – CS: Equals and Hashcode, Covariant Equals
                                    ,
       – FB: Class defines equals and uses Object.hashCode




15                 Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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
switch
     • Regeln:
       – default nicht vergessen
       – kein Fall Through
     • CS: Missing Switch Default, Fall Through




17                  Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Protokollierung
     • keine Protokollausgabe auf stdout, stderr
     • "Mal schnell 'ne Ausgabe"
     • Achtung: IDE-Templates!
     • CS: Regexp… mit passendem Pattern




18                Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Exception-Verwendung
     • Werfen und Fangen von Throwable,
       Exception, RuntimeException i. A. fehlerhaft

     • CS: Illegal Catch, Illegal Throws




19                Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
DRY
     • Keine Copy&Paste-Programmierung

     • CS: Strict Duplicate Code
       (nicht wirklich empfehlenswert)




20                 Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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
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 Typparametern




22                    Gute Zeilen, schlechte Zeilen     dirk.weil@gedoplan.de
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 Entities

23                   Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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




24                  Gute Zeilen, schlechte Zeilen     dirk.weil@gedoplan.de
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-Daten




25                   Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Klassen sparen lohnt nicht
     • Anschauungsbeispiel "Wachdienst"
       – Besser: Zusätzliche Ebene für Etagen

       – Klares Konzept
         Real World   Klasse




26                  Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Wohin mit der Logik?




27     Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
Wohin mit der Logik?
     • Anschauungsbeispiel "Modellbahnsteuerung":
       – Reservieren einer Fahrstraße
         = Stellen der betroffenen
           Weichen und Signale
       – Fahrstrasse liegt als
         Geschäftsobjekt vor

       – Anforderung als Webservice




28                  Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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
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
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 übersichtlicher



31                  Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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
Packages
     • Zwei Anti-Beispiele




33                 Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de
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
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
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
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
Gute Zeilen, schlechte Zeilen   dirk.weil@gedoplan.de

Weitere ähnliche Inhalte

Andere mochten auch

Workshop Formularprozesse mit Adobe Druckformulare in SAP ERP
Workshop Formularprozesse mit Adobe Druckformulare in SAP ERPWorkshop Formularprozesse mit Adobe Druckformulare in SAP ERP
Workshop Formularprozesse mit Adobe Druckformulare in SAP ERPanthesis GmbH
 
MANUAL FOTOGRAFÍA BASICA
MANUAL FOTOGRAFÍA BASICA MANUAL FOTOGRAFÍA BASICA
MANUAL FOTOGRAFÍA BASICA JimenezRuthy
 
Axel Wolpert: Computergestütztes Lernen - was geht heute Ein Überblick
Axel Wolpert: Computergestütztes Lernen - was geht heute Ein ÜberblickAxel Wolpert: Computergestütztes Lernen - was geht heute Ein Überblick
Axel Wolpert: Computergestütztes Lernen - was geht heute Ein Überblicklernet
 
Geschlecht Und Demokratie
Geschlecht Und DemokratieGeschlecht Und Demokratie
Geschlecht Und Demokratieguesta6eca45
 
Einführung
EinführungEinführung
EinführungSchestak
 
Relicamp12 Responsive Webdesign und Webapps
Relicamp12 Responsive Webdesign und WebappsRelicamp12 Responsive Webdesign und Webapps
Relicamp12 Responsive Webdesign und WebappsMaria Herrmann
 
Inductiekappen Voltooid Verleden Tijd
Inductiekappen Voltooid Verleden TijdInductiekappen Voltooid Verleden Tijd
Inductiekappen Voltooid Verleden Tijdoverke
 
PRESENTACIÓN DE LOS BUZOS
PRESENTACIÓN DE LOS BUZOSPRESENTACIÓN DE LOS BUZOS
PRESENTACIÓN DE LOS BUZOSALVAREZDESEGURA
 
Inga Geisler: Ich nenne es WEBINAR - und Sie?
Inga Geisler: Ich nenne es WEBINAR - und Sie?Inga Geisler: Ich nenne es WEBINAR - und Sie?
Inga Geisler: Ich nenne es WEBINAR - und Sie?lernet
 
Tutorial 2 - Einen Blog abonnieren
Tutorial 2 - Einen Blog abonnierenTutorial 2 - Einen Blog abonnieren
Tutorial 2 - Einen Blog abonnierenSchestak
 
Kai Bollue Regelungstechnik
Kai  Bollue    RegelungstechnikKai  Bollue    Regelungstechnik
Kai Bollue Regelungstechnikguest13d677
 
Ulrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzen
Ulrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzenUlrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzen
Ulrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzenlernet
 
о дежурстве
о дежурствео дежурстве
о дежурствеpkgpkg
 
JSCS — архитектура, история и будущее — Олег Гайдаренко
JSCS — архитектура, история и будущее — Олег ГайдаренкоJSCS — архитектура, история и будущее — Олег Гайдаренко
JSCS — архитектура, история и будущее — Олег ГайдаренкоYandex
 
MQ BMUKK Literacy Symposium 2009
MQ BMUKK  Literacy Symposium 2009MQ BMUKK  Literacy Symposium 2009
MQ BMUKK Literacy Symposium 2009joness6
 

Andere mochten auch (20)

Workshop Formularprozesse mit Adobe Druckformulare in SAP ERP
Workshop Formularprozesse mit Adobe Druckformulare in SAP ERPWorkshop Formularprozesse mit Adobe Druckformulare in SAP ERP
Workshop Formularprozesse mit Adobe Druckformulare in SAP ERP
 
MANUAL FOTOGRAFÍA BASICA
MANUAL FOTOGRAFÍA BASICA MANUAL FOTOGRAFÍA BASICA
MANUAL FOTOGRAFÍA BASICA
 
Axel Wolpert: Computergestütztes Lernen - was geht heute Ein Überblick
Axel Wolpert: Computergestütztes Lernen - was geht heute Ein ÜberblickAxel Wolpert: Computergestütztes Lernen - was geht heute Ein Überblick
Axel Wolpert: Computergestütztes Lernen - was geht heute Ein Überblick
 
Célula animal
Célula animal Célula animal
Célula animal
 
Pisa studie
Pisa studiePisa studie
Pisa studie
 
JUST
JUSTJUST
JUST
 
Geschlecht Und Demokratie
Geschlecht Und DemokratieGeschlecht Und Demokratie
Geschlecht Und Demokratie
 
Einführung
EinführungEinführung
Einführung
 
Relicamp12 Responsive Webdesign und Webapps
Relicamp12 Responsive Webdesign und WebappsRelicamp12 Responsive Webdesign und Webapps
Relicamp12 Responsive Webdesign und Webapps
 
Inductiekappen Voltooid Verleden Tijd
Inductiekappen Voltooid Verleden TijdInductiekappen Voltooid Verleden Tijd
Inductiekappen Voltooid Verleden Tijd
 
Bericht 2
Bericht 2Bericht 2
Bericht 2
 
PRESENTACIÓN DE LOS BUZOS
PRESENTACIÓN DE LOS BUZOSPRESENTACIÓN DE LOS BUZOS
PRESENTACIÓN DE LOS BUZOS
 
Inga Geisler: Ich nenne es WEBINAR - und Sie?
Inga Geisler: Ich nenne es WEBINAR - und Sie?Inga Geisler: Ich nenne es WEBINAR - und Sie?
Inga Geisler: Ich nenne es WEBINAR - und Sie?
 
Tutorial 2 - Einen Blog abonnieren
Tutorial 2 - Einen Blog abonnierenTutorial 2 - Einen Blog abonnieren
Tutorial 2 - Einen Blog abonnieren
 
a2n Awards
a2n Awardsa2n Awards
a2n Awards
 
Kai Bollue Regelungstechnik
Kai  Bollue    RegelungstechnikKai  Bollue    Regelungstechnik
Kai Bollue Regelungstechnik
 
Ulrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzen
Ulrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzenUlrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzen
Ulrich Winchenbach: Virtuelle Seminare für betriebliche Weiterbildung nutzen
 
о дежурстве
о дежурствео дежурстве
о дежурстве
 
JSCS — архитектура, история и будущее — Олег Гайдаренко
JSCS — архитектура, история и будущее — Олег ГайдаренкоJSCS — архитектура, история и будущее — Олег Гайдаренко
JSCS — архитектура, история и будущее — Олег Гайдаренко
 
MQ BMUKK Literacy Symposium 2009
MQ BMUKK  Literacy Symposium 2009MQ BMUKK  Literacy Symposium 2009
MQ BMUKK Literacy Symposium 2009
 

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

JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013Oliver Zeigermann
 
Javascript done right
Javascript done rightJavascript done right
Javascript done rightDirk Ginader
 
Ruby und Rails für .NET Entwickler
Ruby und Rails für .NET EntwicklerRuby und Rails für .NET Entwickler
Ruby und Rails für .NET EntwicklerNETUserGroupBern
 
An Introduction to Ruby
An Introduction to RubyAn Introduction to Ruby
An Introduction to RubyJonathan Weiss
 
Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!
Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!
Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!Benjamin Schmid
 
Grails im Überblick und in der Praxis
Grails im Überblick und in der PraxisGrails im Überblick und in der Praxis
Grails im Überblick und in der PraxisTobias Kraft
 
Puppet: Designing modules & repositories
Puppet: Designing modules & repositoriesPuppet: Designing modules & repositories
Puppet: Designing modules & repositoriesinovex GmbH
 
Java und Go im Vergleich
Java und Go im VergleichJava und Go im Vergleich
Java und Go im VergleichQAware GmbH
 
Speeding up Java Persistence
Speeding up Java PersistenceSpeeding up Java Persistence
Speeding up Java Persistencegedoplan
 
BED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerBED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerPatrick Baumgartner
 
The Lotus Code Cookbook
The Lotus Code CookbookThe Lotus Code Cookbook
The Lotus Code CookbookUlrich Krause
 
Drupal Multisite und Subversion
Drupal Multisite und SubversionDrupal Multisite und Subversion
Drupal Multisite und SubversionDrupalist
 
Einführung in Clean Code mit .NET - Teil 1
Einführung in Clean Code mit .NET - Teil 1Einführung in Clean Code mit .NET - Teil 1
Einführung in Clean Code mit .NET - Teil 1Gregor Biswanger
 
Dart (Teil I der Tour de Dart)
Dart (Teil I der Tour de Dart)Dart (Teil I der Tour de Dart)
Dart (Teil I der Tour de Dart)Nane Kratzke
 
Nigh Session Scala
Nigh Session ScalaNigh Session Scala
Nigh Session Scalaadesso AG
 
Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...
Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...
Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...André Krämer
 
FH Wedel - SS11 - Seminar - Marcus Riemer - LEDA
FH Wedel - SS11 - Seminar - Marcus Riemer - LEDAFH Wedel - SS11 - Seminar - Marcus Riemer - LEDA
FH Wedel - SS11 - Seminar - Marcus Riemer - LEDAMarcus Riemer
 
TDD mit ABAP Units
TDD mit ABAP UnitsTDD mit ABAP Units
TDD mit ABAP UnitsCadaxo GmbH
 

Ähnlich wie Vortrag Dirk Weil Gute zeilen, schlechte Zeilen auf der JAX 2012 (20)

JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013
 
Javascript done right
Javascript done rightJavascript done right
Javascript done right
 
Ruby und Rails für .NET Entwickler
Ruby und Rails für .NET EntwicklerRuby und Rails für .NET Entwickler
Ruby und Rails für .NET Entwickler
 
An Introduction to Ruby
An Introduction to RubyAn Introduction to Ruby
An Introduction to Ruby
 
Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!
Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!
Auf dem Weg zu Unwartbarkeit - Die besten Strategien für den sicheren Erfolg!
 
Grails im Überblick und in der Praxis
Grails im Überblick und in der PraxisGrails im Überblick und in der Praxis
Grails im Überblick und in der Praxis
 
Puppet: Designing modules & repositories
Puppet: Designing modules & repositoriesPuppet: Designing modules & repositories
Puppet: Designing modules & repositories
 
Java und Go im Vergleich
Java und Go im VergleichJava und Go im Vergleich
Java und Go im Vergleich
 
Workshop: Besseres C#
Workshop: Besseres C#Workshop: Besseres C#
Workshop: Besseres C#
 
Speeding up Java Persistence
Speeding up Java PersistenceSpeeding up Java Persistence
Speeding up Java Persistence
 
BED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als EntwicklerBED-Con - Tools für den täglichen Kampf als Entwickler
BED-Con - Tools für den täglichen Kampf als Entwickler
 
The Lotus Code Cookbook
The Lotus Code CookbookThe Lotus Code Cookbook
The Lotus Code Cookbook
 
Drupal Multisite und Subversion
Drupal Multisite und SubversionDrupal Multisite und Subversion
Drupal Multisite und Subversion
 
Einführung in Clean Code mit .NET - Teil 1
Einführung in Clean Code mit .NET - Teil 1Einführung in Clean Code mit .NET - Teil 1
Einführung in Clean Code mit .NET - Teil 1
 
Dart (Teil I der Tour de Dart)
Dart (Teil I der Tour de Dart)Dart (Teil I der Tour de Dart)
Dart (Teil I der Tour de Dart)
 
Nigh Session Scala
Nigh Session ScalaNigh Session Scala
Nigh Session Scala
 
Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...
Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...
Das Repository-Pattern und der O/R-Mapper: Geniale Kombination oder vergebene...
 
FH Wedel - SS11 - Seminar - Marcus Riemer - LEDA
FH Wedel - SS11 - Seminar - Marcus Riemer - LEDAFH Wedel - SS11 - Seminar - Marcus Riemer - LEDA
FH Wedel - SS11 - Seminar - Marcus Riemer - LEDA
 
TDD mit ABAP Units
TDD mit ABAP UnitsTDD mit ABAP Units
TDD mit ABAP Units
 
Ruby on Rails SS09 06
Ruby on Rails SS09 06Ruby on Rails SS09 06
Ruby on Rails SS09 06
 

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

  • 1. Gute Zeilen, schlechte Zeilen Regeln für wartbare Programme Dirk Weil | GEDOPLAN
  • 2. Dirk Weil • GEDOPLAN GmbH, Bielefeld • Java EE seit 1998 • Konzeption und Realisierung • Vorträge • Seminare • Veröffentlichungen 2 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 3. GUTE ZEILEN SCHLECHTE ZEILEN 3 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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 sein 4 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 5. Gibt es guten und schlechten Code? • Entwicklerteams sind meist heterogen – Berufserfahrung – Programmierstil –… • Richtlinien helfen – bei der Einarbeitung in fremde Software – bei der (Weiter-) Entwicklung 5 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 6. Richtlinien Low Level: Namen, Formatierung … Grundlegendes Klassendesign Code-Komplexität Anwendungsstruktur 6 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 7. Statische Code-Analyse • Matching des Codes gegen Regelsätze • Einfache (Text-)Pattern … strukturelle Pattern Checkstyle 7 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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 = true 8 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. 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. 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 Bedeutung 11 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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 zweitrangig 12 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. 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 code 14 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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.hashCode 15 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. switch • Regeln: – default nicht vergessen – kein Fall Through • CS: Missing Switch Default, Fall Through 17 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 18. Protokollierung • keine Protokollausgabe auf stdout, stderr • "Mal schnell 'ne Ausgabe" • Achtung: IDE-Templates! • CS: Regexp… mit passendem Pattern 18 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 19. Exception-Verwendung • Werfen und Fangen von Throwable, Exception, RuntimeException i. A. fehlerhaft • CS: Illegal Catch, Illegal Throws 19 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 20. DRY • Keine Copy&Paste-Programmierung • CS: Strict Duplicate Code (nicht wirklich empfehlenswert) 20 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. 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 Typparametern 22 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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 Entities 23 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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 abgehakt 24 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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-Daten 25 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 26. Klassen sparen lohnt nicht • Anschauungsbeispiel "Wachdienst" – Besser: Zusätzliche Ebene für Etagen – Klares Konzept Real World Klasse 26 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 27. Wohin mit der Logik? 27 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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 Webservice 28 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. 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. 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 übersichtlicher 31 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. Packages • Zwei Anti-Beispiele 33 Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de
  • 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. 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. 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. 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. Gute Zeilen, schlechte Zeilen dirk.weil@gedoplan.de