SlideShare ist ein Scribd-Unternehmen logo
Java Code Quality


Regeln für gute Java-Programme



Treffpunkt Semicolon, 22.02.2011, GFU Cyrus AG
Jens Seekamp, GEDOPLAN GmbH
Java Code Quality – ein ganzheitlicher Ansatz

Agenda

  Software-Qualität
  Regel 1: System-Dekomposition und Build-Prozess
  Regel 2: Schichten-Architektur
  Regel 3: Modell-getriebene Entwicklung
  Regel 4: inkrementelle Entwicklung
  Regel 5: Richtlinien und statische Code-Analyse
  Regel 6: integrierter, automatisierter Test
  Regel 7: Refactoring und Regressionstest


                                                    2
Software-Qualität

  Strukturierung (System, Komponente, Schicht, Paket, Klasse, Methode,
  Anweisung)
  Einheitlichkeit (Generierung, Muster)
  Richtlinien-Konformität (statische Programm-Analyse)
  Verständlichkeit (Funktionalität / Logik der Software-Elemente)
  Lesbarkeit (Bezeichner, Formatierung, ...)
  Dokumentation, Kommentare (JavaDoc)
  Korrektheit und Stabilität (funktionaler Programm-Test)
  Leistungsfähigkeit (Performanz, Last), Benutzerfreundlichkeit
  Wartbarkeit (Fehlerbehebung, Change Requests)
  Erweiterbarkeit (neue Anforderungen)

                                                                         3
Regel 1: System-Dekomposition und Build-Prozess

  System-Dekomposition
     Zerlegung des Software-Systems in Komponenten
     eine Komponente kapselt einen Funktionsbereich (Schnittstelle
     vs. Rumpf)
     eine Komponente basiert oftmals auf einer Implementierungs-
     Technologie (z. B. EJB)
     eine Komponente ist i. d. R. ausführbar




                                                                     4
Architektur einer „kleinen“ Java-EE-Anwendung

                                            Projekt PRAGSYS:
                                            Prüfsystem für Statistiken
                                            der GKV




                                                                         5
Architektur einer „großen“ Java-EE-Anwendung
                                         Projekt BDE:
                                         Betriebsdatenerfassung für
                                         Fertigungsindustrie




                                                                      6
Regel 1: System-Dekomposition und Build-Prozess

  Build-Prozess
     „Bauen“ des Software-Systems aus seinen kompilierten
     Komponenten
     dabei wird je Komponente ein Build-Artefakt erstellt

  Werkzeuge für den Build-Prozess
    Build-Prozess wird vollständig mit Maven 3.x durchgeführt
    Java-Compiler der IDE ist (theoretisch) überflüssig
    Continuous Integration wird mit Hudson realisiert (z. B. Nightly
    Build)


                                                                   7
Maven-Multi-Projekt für Java-EE-Anwendung
<project>

<groupId>de.gedoplan.bde</groupId>                  <project>
<artifactId>bde</artifactId>
<version>1.0.0</version>                            <parent>
                                                      <groupId>de.gedoplan.bde</groupId>
<modules>                                             <artifactId>bde</artifactId>
  <module>bde-common</module>                         <version>1.0.0</version>
  <module>bde-comp-mitarbeiter</module>             </parent>
  <module>bde-comp-zeiterfassung</module>
  <module>bde-web</module>                          <artifactId>bde-comp-mitarbeiter</artifactId>
  <module>bde-ear</module>                          <packaging>ejb</packaging>
</modules>


                                                                <project>
       <project>
                                                                <parent> ...
       <parent> ...
                                                                <artifactId>bde-web</artifactId>
       <artifactId>bde-ear</artifactId>                         <packaging>war</packaging>
       <packaging>ear</packaging>

       <dependencies>
         ... <artifactId>bde-comp-mitarbeiter ...
         ... <artifactId>bde-web ...


                                                                                                    8
Regel 2: Schichten-Architektur

  Zerlegung in 3-Schichten-Architektur
      Präsentations-Schicht (GUI)
      Fachlogik-Schicht (Geschäftsfälle, Dienste, Fachklassen)
      Datenhaltungs-Schicht (Speicherung der Objekte, RDBMS)
  zusätzlich oftmals „übergreifende“ Schichten
      fachliches Klassenmodell (Entitäten)
      Basis-Dienste und –Klassen (z. B. Ausnahmen, Meldungen)

  Schichten-Zerlegung ist möglich
     auf Ebene des Software-Systems
     auf Ebene der Komponenten
                                                                 9
Schichten-Architektur einer Java-EE-Anwendung




                                                10
Sicherstellung der Schichten-Architektur

  häufige Verletzungen der Schichten-Architektur
     „Überspringen“ einer Schicht (Präsentation Datenhaltung)
     „umgekehrte“ benutzt-Beziehung (Datenhaltung Fachlogik)
     falsche Zuordnung von Implementierung
        Realisierung von fachlicher Logik in Dialogklassen
        erkennbar in Benutzung von Fachklassen anstelle von Dienst-Schnittstelle


  Sicherstellung durch Spezifikation von
     erlaubten benutzt-Beziehungen
     nicht erlaubten benutzt-Beziehungen


                                                                              11
Sicherstellung mit Checkstyle-Modul „Import Control“




                                                       12
Regel 3: Modell-getriebene Entwicklung

  aus einem „Modell“ generierter Java-Code ist
     strukturiert
     einheitlich
     korrekt und stabil

  Code-Generierung steigert außerdem
     die Effizienz der Software-Entwicklung
     die Wartbarkeit des Software-Systems




                                                 13
„klassische“ Modell-getriebene Entwicklung

Generierung                        @Entity
                                   public class Land
  des fachlichen Klassenmodells    {
                                     @Id
  (Entitäten)                        private String isoCode;
                                     private String name;

  als POJO-Klassen mit JPA-            public Land()

  Annotationen                         {}

                                       public String getIsoCode()
  aus UML-Klassenmodell (z. B.         { return this.isoCode; }

  Enterprise Architect)                public void setIsoCode(String code)
                                       { this.isoCode = code; }

                                       public String getName()
                                       { return this.name; }

                                       public void setName(String name)
                                       { this.name = name; }
                                   }




                                                                          14
Generierung von XML-Zugriffsklassen (1)

Generierung
  für die Umwandlung Java-Objekte      XML-Dokumente
  (Marshalling / Unmarshalling)
  als POJO-Klassen mit JAXB-Annotationen
  aus XML-Schema (z. B. XMLSPY)
  mit dem JAXB-Schema-Compiler (Java Architecture for XML
  Binding)




                                                            15
Generierung von XML-Zugriffsklassen (2)

                                              XJC




                            @XmlAccessorType(XmlAccessType.FIELD)
                            @XmlType(name = "Satzart_Ctp", propOrder =
                              {"verfahren", "zeitraumAb", "zeitraumBis"})

                            public class Satzart implements Serializable
                            {
                              @XmlElement(name = "Verfahren", required = true)
                              private String verfahren;

                              public String getVerfahren()
                              { return verfahren; }

                              public void setVerfahren(String daten)
                              { verfahren = daten; }




                                                                            16
Generierung eines Formel-Parser
Generierung
  eines Parser für arithmetisch-logische Formeln
  aus einer kontextfreien Grammatik
  mit dem Parser-Generator JavaCC (Java Compiler Compiler)
 TOKEN: {
 | < PLUS: "+" >                                                  12 * x + 5 ...
 | < MINUS: "-" >
 }

 void Addition():
 { Token t = null;
   StringBuilder sb = new StringBuilder();
 }                                                                              +
 { Multiplikation()
   ( ( t = <PLUS> Multiplikation() ) { sb.append(t.image); }
     | ( t = <MINUS> Multiplikation() ) { sb.append(t.image); }         *           5
   )*
   { jjtThis.jjtSetValue(sb.toString()); }
 }                                                                 12       x



                                                                                        17
Regel 4: inkrementelle Entwicklung - Randbedingungen




   package de.aoksystems.pragsys.service.pruefkern;

   import de.aoksystems.pragsys.bo.statistik.Statistik;
   import de.aoksystems.pragsys.bo.pruefung.Pruefergebnis;

   @Stateless
   public class PruefServiceBean implements PruefService
   {
     /**
      * Diese Methode prüft eine Statistik, die an das Prüfsystem
      * übergeben wurde, und liefert das Prüfergebnis zurück.
      */
     public Pruefergebnis pruefeStatistik(Statistik s)
     {...}
   }




                                                                    18
Regel 4: inkrementelle Entwicklung - Tipps

  Implementierung: konkret beginnen und schrittweise verfeinern
  erst „in die Tiefe“, später „in die Breite“ implementieren (Prototyping,
  depth-first)
  möglichst frühe Rückkopplung
     gleichzeitige Erstellung von Unit-Tests
     Review durch Projekt-Kollegen
     Demonstration für Benutzer
  Grundsätze beachten (vgl. http://www.clean-code-developer.de)
     immer objektorientiert und „sauber“
     möglichst einfach (KISS), redundanzfrei (DRY), ...
  „Software ist (fast) nie fertig.“ (evolutionäre Entwicklung, TODOs)

                                                                        19
Regel 5: Richtlinien und statische Code-Analyse

  ein Team von SW-Entwicklern ist heterogen (Berufs-/Projekterfahrung,
  Programmierstil)
  für einheitlichen, lesbaren, kommentierten usw. Java-Code sind
  Entwicklungs-Richtlinien unabdingbar
  Richtlinien-Katalog zusammengefasst im Entwickler-Handbuch
      Beschreibung der Richtlinie (ggf. mit Motivation, Zielsetzung)
      Positiv- und ggf. Negativ-Beispiele (Do‘s and Dont‘s)
  Umfang des Programm-Code und Anzahl der Richtlinien erfordern
  automatisierte Überwachung
  Werkzeuge für die statische Code-Analyse
      z. B. Checkstyle, FindBugs, SonarJ

                                                                     20
Regel 5: Richtlinien-Katalog (Beispiele)

  Standard-Konventionen für Java der Firma Sun
  deutsche Bezeichner für Klassen, Attribute, Methoden etc.
  verwenden
  Konstanten bestehen nur aus Großbuchstaben, Ziffern und dem
  Unterstrich "_"
  anstatt null ein Array der Länge 0 zurück geben
  falls eine Exception geworfen wird, muss sie protokolliert
  werden
  mehrmals benötigte Programmlogik wird in eine separate Methode
  bzw. Klasse ausgelagert
  Reflection darf nicht verwendet werden

                                                               21
Regel 5: Werkzeuge für statische Code-Analyse

  Idealfall: für jede Richtlinie gibt es eine aktivierte Analyse-Regel
  und umgekehrt
  für „kleine“ Projekte sollte ein Code-Analyse-Werkzeug reichen
  für „große“ Projekte und Vollständigkeit müssen ggf. mehrere Code-
  Analyse-Werkzeuge parallel eingesetzt werden
     erhöhter Konfigurationsaufwand
     Problem der Mehrfach-Meldung von Verletzungen
  Standardisierung / Wiederverwendung des Richtlinien-Kataloges und
  der Werkzeug-Konfiguration (über Projekt- und Abteilungsgrenzen)
  Werkzeuge machen Reviews durch Software-Architekten oder
  erfahrene Entwickler nicht überflüssig


                                                                   22
Beispiel: Code-Bereinigung mittels Checkstyle / Review
               (5)   Import-Organisation, Formatierung
               (4)   Namenskonventionen, Bezeichner, for
               (3)   JavaDoc, Anweisungs-Struktur, Kommentare
               (2)   try-catch, Parameterprüfung
               (1)   Ausnahmebehandlung, Logging
                     „Nice“




                                                                23
Regel 6: integrierter, automatisierter Test

  Software-Test hat zwei Zielsetzungen
      im Java-Code möglichst viele Fehler aufdecken
      Korrektheit der Anwendung demonstrieren
  Test ist integraler Bestandteil der Software-Entwicklung, und nicht
  nur nachgelagert (vgl. testgetriebene Entwicklung, test-first)
  Test dient zum Nachweis der dynamischen, funktionalen Korrektheit
  des Java-Code (dies ist mit statischer Code-Analyse nicht möglich)
  Fokus liegt auf der Realisierung von automatisierten Tests
  dafür Einsatz von Java-Test-Frameworks und –Werkzeugen




                                                                  24
Regel 6: Test-Konzeption für Java-(EE)-Anwendungen

  Schritt 1: Entwicklertest für wichtige Klassen und Methoden
     „Standard“-Framework JUnit 4.x
  Schritt 2: Realisierung einer Testdaten-Verwaltung
     Nutzung dedizierter Test-Datenbank(en)
     explizite Testdaten-Erzeugung mittels Java (DBUnit, XMLUnit)
  Schritt 3: Integrationstest der Service-Schicht
     per JUnit-Testclient gegen den Application-Server (remote)
     mittels z. B. OpenEJB innerhalb der IDE (embedded)
  Schritt 4: „automatisierter Abnahmetest“ der GUI-Clients
     Werkzeug abhängig von GUI-Technologie und –Bibliothek
     z. B. QF-Test (alle), Selenium (Web), Abbot (Swing)
  Schritt 5: Test nicht-funktionaler Anforderungen (Performanz, Last)

                                                                        25
Regel 6: Bibliothek der automatisierten Testfälle

  Zusammenfassung aller automatisierten Testfälle aus Schritt 1 bis 5
  zu einer Test-Bibliothek
                                            als Test-Suites gemäß JUnit
                                            (JUnit-Integration aller Werkzeuge /
                                            Frameworks vorausgesetzt)
                                            hierarchische Strukturierung
                                            der Test-Suites
                                            gesamte Test-Bibliothek auf
                                            Entwicklungsrechner lokal
                                            ausführbar




                                                                            26
Regel 7: Refactoring und Regressionstest
  Fehler und Qualitätsmängel des Java-Code werden laufend
  festgestellt durch
      werkzeuggestützte, automatisierte Tests
      werkzeuggestützte, statische Code-Analyse
  direkte Notwendigkeit für Fehlerbehebung und Mängelbeseitigung
  bedingt oftmals Refactoring, d. h. weitergehende, strukturelle
  „Umbau-Arbeiten“
  nach einem Refactoring
      ist der Java-Code fehlerbereinigt und / oder qualitativ besser
      ist die Gesamt-Funktionalität unverändert


                                                                   27
Beispiel: Redundanz-Beseitigung und Kapselung
                   Aufdecken von redundantem Java-Code mit
                   Checkstyle-Modul „Strict Duplicate Code“
                   Auslagern der Code-Redundanz in eine separate
                   Klasse
                   dadurch gleichzeitig Kapselung der Verwendung
                   des JAXB-Framework




                                                                   28
Regel 7: Regressionstest im Rahmen der CI

  Wahrung der funktionalen Korrektheit nach Refactorings wird durch
  den Regressionstest sichergestellt
  Regressionstest ist der Test des gesamten Java-Code auf Basis der
  Test-Bibliothek
  Zusammenfassung aller automatisierten, qualitätssichernden
  Maßnahmen in der Continuous Integration (Hudson):
     Integrations-Build (Subversion, Maven)
     Generierung der Programm-Dokumentation (JavaDoc)
     statische Code-Analyse (Checkstyle, ...)
     Regressionstest (JUnit, ...) auf Basis der Test-Bibliothek
     Messung der Test-Überdeckung (Cobertura)
     Deployment auf QS-Umgebung (für manuelle Tests)

                                                                  29

Weitere ähnliche Inhalte

PDF
Softwarequalitätssicherung mit Continuous Integration Tools
PDF
Requirements Engineering in agilen Projekten - Flexibilität ist gefordert
PDF
Cross-Apps-Entwicklung für iPhone, Android und Co.
PDF
Neue Features der Java EE 6
PDF
Continuous Integration mit Hudson (JUG Stuttgart, 11.02.2010)
PDF
Continuous Integration mit Hudson (JUG Mannheim, 27.01.2010)
PDF
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
PDF
Einführung Vorgehensmodelle und Agile Software Entwicklung
Softwarequalitätssicherung mit Continuous Integration Tools
Requirements Engineering in agilen Projekten - Flexibilität ist gefordert
Cross-Apps-Entwicklung für iPhone, Android und Co.
Neue Features der Java EE 6
Continuous Integration mit Hudson (JUG Stuttgart, 11.02.2010)
Continuous Integration mit Hudson (JUG Mannheim, 27.01.2010)
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
Einführung Vorgehensmodelle und Agile Software Entwicklung

Was ist angesagt? (20)

PDF
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
PDF
Von Maven zu Gradle in 45 Minuten
PDF
Objektvalidierung mit dem Bean Validation Api
PDF
Regulatorics: Offside is when the referee whistles - DOAG 2018
PDF
PDF
Professionelle Anforderungsanalyse am Beispiel einer Java-Anwendung zur Betri...
PDF
Test Management mit Visual Studio 2012
PDF
Web-GUIs mit Vaadin
PDF
Anforderungsanalyse und UML Grundlagen
PDF
Plsql drum test automatisiere, wer sich sich ewig bindet! - DOAG 2017
PDF
Implementierung der Knowledge Engineering Workbench in myCBR
PDF
Softwarequalität Entwicklung - Test - Wartung
PDF
Anforderungsanalyse - Grundlagen und Prototyping
PDF
Vortragsreihe Dortmund: Unified Development Environments
PDF
Javamagazin 1.2016 jdk9_ea_b83_jigsaw
PDF
Systementwurf mit UML
PPTX
Configuration Management (Fokus: Version-Controlling) – Best Pracitces
PDF
Agile Oracle database modeling and development - APEX Connect 2020
PDF
Prozesse im Spiegel des Projektalltags
PDF
Java für eingebettete Systeme
javaPersistenceInActionFeaturesJenseitsDesEntryLevels
Von Maven zu Gradle in 45 Minuten
Objektvalidierung mit dem Bean Validation Api
Regulatorics: Offside is when the referee whistles - DOAG 2018
Professionelle Anforderungsanalyse am Beispiel einer Java-Anwendung zur Betri...
Test Management mit Visual Studio 2012
Web-GUIs mit Vaadin
Anforderungsanalyse und UML Grundlagen
Plsql drum test automatisiere, wer sich sich ewig bindet! - DOAG 2017
Implementierung der Knowledge Engineering Workbench in myCBR
Softwarequalität Entwicklung - Test - Wartung
Anforderungsanalyse - Grundlagen und Prototyping
Vortragsreihe Dortmund: Unified Development Environments
Javamagazin 1.2016 jdk9_ea_b83_jigsaw
Systementwurf mit UML
Configuration Management (Fokus: Version-Controlling) – Best Pracitces
Agile Oracle database modeling and development - APEX Connect 2020
Prozesse im Spiegel des Projektalltags
Java für eingebettete Systeme
Anzeige

Ähnlich wie Java Code Quality: Gute Software braucht guten Code - Regeln für verständliche und wartbare Java-Programme (20)

PDF
Gradle - Beginner's Workshop (german)
PDF
Funktionale Programmierung mit Java - Andreas Jürgensen
PDF
Python builds mit ant
PDF
Java EE 5
PDF
SOLID Prinzipien, Designgrundlagen objektorientierter Systeme
PDF
Lightweight AOP with CDI and JPA
PDF
Backbase Intro
PPT
Workshop zu Hibernate 3.2.2 GA
PDF
MicroProfile-Anwendungen mit Quarkus
PDF
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
PDF
Feige sein! Testen im Java-EE-Umfeld
PDF
Microprofile-Anwendungen mit Quarkus
PDF
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
PDF
Mögen die Tests mit dir sein
ODP
Einfacher bauen
PPTX
Real Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
PDF
EnterJS 2015 - JavaScript von Morgen schon heute
ODP
Scala - OSGi Bundles from Outer (Java) Space
PDF
GWT – Google Web Toolkit in der Praxis
PDF
JEE-Microservices mit Quarkus – eine Einführung
Gradle - Beginner's Workshop (german)
Funktionale Programmierung mit Java - Andreas Jürgensen
Python builds mit ant
Java EE 5
SOLID Prinzipien, Designgrundlagen objektorientierter Systeme
Lightweight AOP with CDI and JPA
Backbase Intro
Workshop zu Hibernate 3.2.2 GA
MicroProfile-Anwendungen mit Quarkus
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Feige sein! Testen im Java-EE-Umfeld
Microprofile-Anwendungen mit Quarkus
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Mögen die Tests mit dir sein
Einfacher bauen
Real Application Testing - DOAG SIG Database 2010 - Simon Dickmeiß
EnterJS 2015 - JavaScript von Morgen schon heute
Scala - OSGi Bundles from Outer (Java) Space
GWT – Google Web Toolkit in der Praxis
JEE-Microservices mit Quarkus – eine Einführung
Anzeige

Mehr von GFU Cyrus AG (20)

PDF
Social Media im Unternehmen
PDF
Clean Code Developer
PDF
Datenschutz bei Facebook & Co. - Wie schütze ich meine persönlichen Daten im ...
PDF
SharePoint 2010 - Was ist neu, was wird besser!
PDF
Java Persistence 2.0
PDF
Pragmatische Einführung von IT-Servicemanagement - ITIL im Unternehmen - Erfa...
PDF
Liferay Portal - ein Webportal für viele Unternehmensanforderungen
PDF
PostgreSQL im Produktivbetrieb
PDF
Java Server Faces 2.0 - Der Standard für moderne und komponentenbasierte Weba...
PDF
Wieviel Web2.0 braucht Ihr Unternehmen?
PDF
Das Java-Spring-Framework in der Praxis
PDF
Agile Geschäftsprozeßanalyse OOA/D am Beispiel einer Seminarverwaltung
PDF
Wissensmanagement bei Volkswagen
PDF
Grenzüberschreitende Geschäftsprozesse mit Microsoft SharePoint und BizTalk
PDF
Projekt! - Toll - Ein Anderer Macht`s! - Voraussetzungen für eine erfolgreich...
PDF
Standardsoftware in der Versicherungsbranche - Betrachtung eines Paradigmenwe...
PDF
E-Learning mit Moodle
PDF
LINQ - Einheitlicher Datenzugriff in .NET
PDF
Java oberflächlich betrachtet - Welche GUI ist die richtige?
PDF
Oracle 11g - Neuerungen im Überblick
Social Media im Unternehmen
Clean Code Developer
Datenschutz bei Facebook & Co. - Wie schütze ich meine persönlichen Daten im ...
SharePoint 2010 - Was ist neu, was wird besser!
Java Persistence 2.0
Pragmatische Einführung von IT-Servicemanagement - ITIL im Unternehmen - Erfa...
Liferay Portal - ein Webportal für viele Unternehmensanforderungen
PostgreSQL im Produktivbetrieb
Java Server Faces 2.0 - Der Standard für moderne und komponentenbasierte Weba...
Wieviel Web2.0 braucht Ihr Unternehmen?
Das Java-Spring-Framework in der Praxis
Agile Geschäftsprozeßanalyse OOA/D am Beispiel einer Seminarverwaltung
Wissensmanagement bei Volkswagen
Grenzüberschreitende Geschäftsprozesse mit Microsoft SharePoint und BizTalk
Projekt! - Toll - Ein Anderer Macht`s! - Voraussetzungen für eine erfolgreich...
Standardsoftware in der Versicherungsbranche - Betrachtung eines Paradigmenwe...
E-Learning mit Moodle
LINQ - Einheitlicher Datenzugriff in .NET
Java oberflächlich betrachtet - Welche GUI ist die richtige?
Oracle 11g - Neuerungen im Überblick

Java Code Quality: Gute Software braucht guten Code - Regeln für verständliche und wartbare Java-Programme

  • 1. Java Code Quality Regeln für gute Java-Programme Treffpunkt Semicolon, 22.02.2011, GFU Cyrus AG Jens Seekamp, GEDOPLAN GmbH
  • 2. Java Code Quality – ein ganzheitlicher Ansatz Agenda Software-Qualität Regel 1: System-Dekomposition und Build-Prozess Regel 2: Schichten-Architektur Regel 3: Modell-getriebene Entwicklung Regel 4: inkrementelle Entwicklung Regel 5: Richtlinien und statische Code-Analyse Regel 6: integrierter, automatisierter Test Regel 7: Refactoring und Regressionstest 2
  • 3. Software-Qualität Strukturierung (System, Komponente, Schicht, Paket, Klasse, Methode, Anweisung) Einheitlichkeit (Generierung, Muster) Richtlinien-Konformität (statische Programm-Analyse) Verständlichkeit (Funktionalität / Logik der Software-Elemente) Lesbarkeit (Bezeichner, Formatierung, ...) Dokumentation, Kommentare (JavaDoc) Korrektheit und Stabilität (funktionaler Programm-Test) Leistungsfähigkeit (Performanz, Last), Benutzerfreundlichkeit Wartbarkeit (Fehlerbehebung, Change Requests) Erweiterbarkeit (neue Anforderungen) 3
  • 4. Regel 1: System-Dekomposition und Build-Prozess System-Dekomposition Zerlegung des Software-Systems in Komponenten eine Komponente kapselt einen Funktionsbereich (Schnittstelle vs. Rumpf) eine Komponente basiert oftmals auf einer Implementierungs- Technologie (z. B. EJB) eine Komponente ist i. d. R. ausführbar 4
  • 5. Architektur einer „kleinen“ Java-EE-Anwendung Projekt PRAGSYS: Prüfsystem für Statistiken der GKV 5
  • 6. Architektur einer „großen“ Java-EE-Anwendung Projekt BDE: Betriebsdatenerfassung für Fertigungsindustrie 6
  • 7. Regel 1: System-Dekomposition und Build-Prozess Build-Prozess „Bauen“ des Software-Systems aus seinen kompilierten Komponenten dabei wird je Komponente ein Build-Artefakt erstellt Werkzeuge für den Build-Prozess Build-Prozess wird vollständig mit Maven 3.x durchgeführt Java-Compiler der IDE ist (theoretisch) überflüssig Continuous Integration wird mit Hudson realisiert (z. B. Nightly Build) 7
  • 8. Maven-Multi-Projekt für Java-EE-Anwendung <project> <groupId>de.gedoplan.bde</groupId> <project> <artifactId>bde</artifactId> <version>1.0.0</version> <parent> <groupId>de.gedoplan.bde</groupId> <modules> <artifactId>bde</artifactId> <module>bde-common</module> <version>1.0.0</version> <module>bde-comp-mitarbeiter</module> </parent> <module>bde-comp-zeiterfassung</module> <module>bde-web</module> <artifactId>bde-comp-mitarbeiter</artifactId> <module>bde-ear</module> <packaging>ejb</packaging> </modules> <project> <project> <parent> ... <parent> ... <artifactId>bde-web</artifactId> <artifactId>bde-ear</artifactId> <packaging>war</packaging> <packaging>ear</packaging> <dependencies> ... <artifactId>bde-comp-mitarbeiter ... ... <artifactId>bde-web ... 8
  • 9. Regel 2: Schichten-Architektur Zerlegung in 3-Schichten-Architektur Präsentations-Schicht (GUI) Fachlogik-Schicht (Geschäftsfälle, Dienste, Fachklassen) Datenhaltungs-Schicht (Speicherung der Objekte, RDBMS) zusätzlich oftmals „übergreifende“ Schichten fachliches Klassenmodell (Entitäten) Basis-Dienste und –Klassen (z. B. Ausnahmen, Meldungen) Schichten-Zerlegung ist möglich auf Ebene des Software-Systems auf Ebene der Komponenten 9
  • 11. Sicherstellung der Schichten-Architektur häufige Verletzungen der Schichten-Architektur „Überspringen“ einer Schicht (Präsentation Datenhaltung) „umgekehrte“ benutzt-Beziehung (Datenhaltung Fachlogik) falsche Zuordnung von Implementierung Realisierung von fachlicher Logik in Dialogklassen erkennbar in Benutzung von Fachklassen anstelle von Dienst-Schnittstelle Sicherstellung durch Spezifikation von erlaubten benutzt-Beziehungen nicht erlaubten benutzt-Beziehungen 11
  • 12. Sicherstellung mit Checkstyle-Modul „Import Control“ 12
  • 13. Regel 3: Modell-getriebene Entwicklung aus einem „Modell“ generierter Java-Code ist strukturiert einheitlich korrekt und stabil Code-Generierung steigert außerdem die Effizienz der Software-Entwicklung die Wartbarkeit des Software-Systems 13
  • 14. „klassische“ Modell-getriebene Entwicklung Generierung @Entity public class Land des fachlichen Klassenmodells { @Id (Entitäten) private String isoCode; private String name; als POJO-Klassen mit JPA- public Land() Annotationen {} public String getIsoCode() aus UML-Klassenmodell (z. B. { return this.isoCode; } Enterprise Architect) public void setIsoCode(String code) { this.isoCode = code; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } } 14
  • 15. Generierung von XML-Zugriffsklassen (1) Generierung für die Umwandlung Java-Objekte XML-Dokumente (Marshalling / Unmarshalling) als POJO-Klassen mit JAXB-Annotationen aus XML-Schema (z. B. XMLSPY) mit dem JAXB-Schema-Compiler (Java Architecture for XML Binding) 15
  • 16. Generierung von XML-Zugriffsklassen (2) XJC @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Satzart_Ctp", propOrder = {"verfahren", "zeitraumAb", "zeitraumBis"}) public class Satzart implements Serializable { @XmlElement(name = "Verfahren", required = true) private String verfahren; public String getVerfahren() { return verfahren; } public void setVerfahren(String daten) { verfahren = daten; } 16
  • 17. Generierung eines Formel-Parser Generierung eines Parser für arithmetisch-logische Formeln aus einer kontextfreien Grammatik mit dem Parser-Generator JavaCC (Java Compiler Compiler) TOKEN: { | < PLUS: "+" > 12 * x + 5 ... | < MINUS: "-" > } void Addition(): { Token t = null; StringBuilder sb = new StringBuilder(); } + { Multiplikation() ( ( t = <PLUS> Multiplikation() ) { sb.append(t.image); } | ( t = <MINUS> Multiplikation() ) { sb.append(t.image); } * 5 )* { jjtThis.jjtSetValue(sb.toString()); } } 12 x 17
  • 18. Regel 4: inkrementelle Entwicklung - Randbedingungen package de.aoksystems.pragsys.service.pruefkern; import de.aoksystems.pragsys.bo.statistik.Statistik; import de.aoksystems.pragsys.bo.pruefung.Pruefergebnis; @Stateless public class PruefServiceBean implements PruefService { /** * Diese Methode prüft eine Statistik, die an das Prüfsystem * übergeben wurde, und liefert das Prüfergebnis zurück. */ public Pruefergebnis pruefeStatistik(Statistik s) {...} } 18
  • 19. Regel 4: inkrementelle Entwicklung - Tipps Implementierung: konkret beginnen und schrittweise verfeinern erst „in die Tiefe“, später „in die Breite“ implementieren (Prototyping, depth-first) möglichst frühe Rückkopplung gleichzeitige Erstellung von Unit-Tests Review durch Projekt-Kollegen Demonstration für Benutzer Grundsätze beachten (vgl. http://www.clean-code-developer.de) immer objektorientiert und „sauber“ möglichst einfach (KISS), redundanzfrei (DRY), ... „Software ist (fast) nie fertig.“ (evolutionäre Entwicklung, TODOs) 19
  • 20. Regel 5: Richtlinien und statische Code-Analyse ein Team von SW-Entwicklern ist heterogen (Berufs-/Projekterfahrung, Programmierstil) für einheitlichen, lesbaren, kommentierten usw. Java-Code sind Entwicklungs-Richtlinien unabdingbar Richtlinien-Katalog zusammengefasst im Entwickler-Handbuch Beschreibung der Richtlinie (ggf. mit Motivation, Zielsetzung) Positiv- und ggf. Negativ-Beispiele (Do‘s and Dont‘s) Umfang des Programm-Code und Anzahl der Richtlinien erfordern automatisierte Überwachung Werkzeuge für die statische Code-Analyse z. B. Checkstyle, FindBugs, SonarJ 20
  • 21. Regel 5: Richtlinien-Katalog (Beispiele) Standard-Konventionen für Java der Firma Sun deutsche Bezeichner für Klassen, Attribute, Methoden etc. verwenden Konstanten bestehen nur aus Großbuchstaben, Ziffern und dem Unterstrich "_" anstatt null ein Array der Länge 0 zurück geben falls eine Exception geworfen wird, muss sie protokolliert werden mehrmals benötigte Programmlogik wird in eine separate Methode bzw. Klasse ausgelagert Reflection darf nicht verwendet werden 21
  • 22. Regel 5: Werkzeuge für statische Code-Analyse Idealfall: für jede Richtlinie gibt es eine aktivierte Analyse-Regel und umgekehrt für „kleine“ Projekte sollte ein Code-Analyse-Werkzeug reichen für „große“ Projekte und Vollständigkeit müssen ggf. mehrere Code- Analyse-Werkzeuge parallel eingesetzt werden erhöhter Konfigurationsaufwand Problem der Mehrfach-Meldung von Verletzungen Standardisierung / Wiederverwendung des Richtlinien-Kataloges und der Werkzeug-Konfiguration (über Projekt- und Abteilungsgrenzen) Werkzeuge machen Reviews durch Software-Architekten oder erfahrene Entwickler nicht überflüssig 22
  • 23. Beispiel: Code-Bereinigung mittels Checkstyle / Review (5) Import-Organisation, Formatierung (4) Namenskonventionen, Bezeichner, for (3) JavaDoc, Anweisungs-Struktur, Kommentare (2) try-catch, Parameterprüfung (1) Ausnahmebehandlung, Logging „Nice“ 23
  • 24. Regel 6: integrierter, automatisierter Test Software-Test hat zwei Zielsetzungen im Java-Code möglichst viele Fehler aufdecken Korrektheit der Anwendung demonstrieren Test ist integraler Bestandteil der Software-Entwicklung, und nicht nur nachgelagert (vgl. testgetriebene Entwicklung, test-first) Test dient zum Nachweis der dynamischen, funktionalen Korrektheit des Java-Code (dies ist mit statischer Code-Analyse nicht möglich) Fokus liegt auf der Realisierung von automatisierten Tests dafür Einsatz von Java-Test-Frameworks und –Werkzeugen 24
  • 25. Regel 6: Test-Konzeption für Java-(EE)-Anwendungen Schritt 1: Entwicklertest für wichtige Klassen und Methoden „Standard“-Framework JUnit 4.x Schritt 2: Realisierung einer Testdaten-Verwaltung Nutzung dedizierter Test-Datenbank(en) explizite Testdaten-Erzeugung mittels Java (DBUnit, XMLUnit) Schritt 3: Integrationstest der Service-Schicht per JUnit-Testclient gegen den Application-Server (remote) mittels z. B. OpenEJB innerhalb der IDE (embedded) Schritt 4: „automatisierter Abnahmetest“ der GUI-Clients Werkzeug abhängig von GUI-Technologie und –Bibliothek z. B. QF-Test (alle), Selenium (Web), Abbot (Swing) Schritt 5: Test nicht-funktionaler Anforderungen (Performanz, Last) 25
  • 26. Regel 6: Bibliothek der automatisierten Testfälle Zusammenfassung aller automatisierten Testfälle aus Schritt 1 bis 5 zu einer Test-Bibliothek als Test-Suites gemäß JUnit (JUnit-Integration aller Werkzeuge / Frameworks vorausgesetzt) hierarchische Strukturierung der Test-Suites gesamte Test-Bibliothek auf Entwicklungsrechner lokal ausführbar 26
  • 27. Regel 7: Refactoring und Regressionstest Fehler und Qualitätsmängel des Java-Code werden laufend festgestellt durch werkzeuggestützte, automatisierte Tests werkzeuggestützte, statische Code-Analyse direkte Notwendigkeit für Fehlerbehebung und Mängelbeseitigung bedingt oftmals Refactoring, d. h. weitergehende, strukturelle „Umbau-Arbeiten“ nach einem Refactoring ist der Java-Code fehlerbereinigt und / oder qualitativ besser ist die Gesamt-Funktionalität unverändert 27
  • 28. Beispiel: Redundanz-Beseitigung und Kapselung Aufdecken von redundantem Java-Code mit Checkstyle-Modul „Strict Duplicate Code“ Auslagern der Code-Redundanz in eine separate Klasse dadurch gleichzeitig Kapselung der Verwendung des JAXB-Framework 28
  • 29. Regel 7: Regressionstest im Rahmen der CI Wahrung der funktionalen Korrektheit nach Refactorings wird durch den Regressionstest sichergestellt Regressionstest ist der Test des gesamten Java-Code auf Basis der Test-Bibliothek Zusammenfassung aller automatisierten, qualitätssichernden Maßnahmen in der Continuous Integration (Hudson): Integrations-Build (Subversion, Maven) Generierung der Programm-Dokumentation (JavaDoc) statische Code-Analyse (Checkstyle, ...) Regressionstest (JUnit, ...) auf Basis der Test-Bibliothek Messung der Test-Überdeckung (Cobertura) Deployment auf QS-Umgebung (für manuelle Tests) 29