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

29
Java Code Quality Regeln für gute Java-Programme Treffpunkt Semicolon, 22.02.2011, GFU Cyrus AG Jens Seekamp, GEDOPLAN GmbH

description

KurzbeschreibungSoftwarequalität ist keine Spracheigenschaft. In jeder noch so guten Programmiersprache kann man schlechte Programme schreiben – sogar in Java. Herr Seekamp, Senior Consultant bei der GEDOPLAN GmbH, macht in diesem Vortrag anhand von Fallbeispielen aus seinen Projekten deutlich, was verständlichen und wartbaren Code ausmacht, welche Regeln man dafür beherzigen sollte und welche Analysewerkzeuge dabei unterstützen können. InhaltRegeln für guten Java-Code Statische Code-Analyse Refactoring Werkzeuge zur Sicherung der Qualität

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

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

Java Code Quality

Regeln für gute Java-Programme

Treffpunkt Semicolon, 22.02.2011, GFU Cyrus AG

Jens Seekamp, GEDOPLAN GmbH

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

Java Code Quality – ein ganzheitlicher Ansatz

Agenda

Software-Qualität

Regel 1: System-Dekomposition und Build-ProzessRegel 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

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

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

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

Regel 1: System-Dekomposition und Build-Prozess

System-Dekomposition

Zerlegung des Software-Systems in Komponenten

eine Komponente kapselt einen Funktionsbereich (Schnittstelle vs. Rumpf)vs. Rumpf)

eine Komponente basiert oftmals auf einer Implementierungs-Technologie (z. B. EJB)

eine Komponente ist i. d. R. ausführbar

4

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

Architektur einer „kleinen“ Java-EE-Anwendung

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

5

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

Architektur einer „großen“ Java-EE-Anwendung

Projekt BDE:Betriebsdatenerfassung für Fertigungsindustrie

6

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

Regel 1: System-Dekomposition und Build-Prozess

Build-Prozess

„Bauen“ des Software-Systems aus seinen kompilierten Komponenten

dabei wird je Komponente ein Build-Artefakt erstelltdabei wird je Komponente ein Build-Artefakt erstellt

Werkzeuge für den Build-Prozess

Build-Prozess wird vollständig mit Maven 3.x durchgeführtJava-Compiler der IDE ist (theoretisch) überflüssig

Continuous Integration wird mit Hudson realisiert (z. B. NightlyBuild)

7

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

Maven-Multi-Projekt für Java-EE-Anwendung

<project>

<parent><groupId>de.gedoplan.bde</groupId><artifactId>bde</artifactId><version>1.0.0</version>

</parent>

<project>

<groupId>de.gedoplan.bde</groupId><artifactId>bde</artifactId><version>1.0.0</version>

<modules><module>bde-common</module><module>bde-comp-mitarbeiter</module><module >bde- comp- zeiterfassung </ module >

8

<artifactId>bde-comp-mitarbeiter</artifactId><packaging>ejb</packaging>

<module >bde- comp- zeiterfassung </ module ><module>bde-web</module><module>bde-ear</module>

</modules>

<project>

<parent> ...

<artifactId>bde-web</artifactId><packaging>war</packaging>

<project>

<parent> ...

<artifactId>bde-ear</artifactId><packaging>ear</packaging>

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

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

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)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

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

Schichten-Architektur einer Java-EE-Anwendung

10

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

Sicherstellung der Schichten-Architektur

häufige Verletzungen der Schichten-Architektur

„Überspringen“ einer Schicht (Präsentation � Datenhaltung)

„umgekehrte“ benutzt-Beziehung (Datenhaltung � Fachlogik)

falsche Zuordnung von Implementierungfalsche Zuordnung von ImplementierungRealisierung 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

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

Sicherstellung mit Checkstyle-Modul „Import Control“

12

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

Regel 3: Modell-getriebene Entwicklung

aus einem „Modell“ generierter Java-Code ist

strukturiert

einheitlich

korrekt und stabilkorrekt und stabil

Code-Generierung steigert außerdem

die Effizienz der Software-Entwicklung

die Wartbarkeit des Software-Systems

13

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

„klassische“ Modell-getriebene Entwicklung

@Entitypublic class Land{

@Idprivate String isoCode;private String name;

public Land()

Generierung

des fachlichen Klassenmodells (Entitäten)

als POJO-Klassen mit JPA-

14

public Land(){}

public String getIsoCode(){ return this.isoCode; }

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

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

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

}

als POJO-Klassen mit JPA-Annotationen

aus UML-Klassenmodell (z. B. Enterprise Architect)

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

Generierung von XML-Zugriffsklassen (1)

Generierung

für die Umwandlung Java-Objekte �� XML-Dokumente (Marshalling / Unmarshalling)

als POJO-Klassen mit JAXB-Annotationenals POJO-Klassen mit JAXB-Annotationen

aus XML-Schema (z. B. XMLSPY)mit dem JAXB-Schema-Compiler (Java Architecture for XML Binding)

15

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

Generierung von XML-Zugriffsklassen (2)

XJC

16

@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; }

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

Generierung eines Formel-Parser

Generierung

eines Parser für arithmetisch-logische Formeln

aus einer kontextfreien Grammatik

mit dem Parser-Generator JavaCC (Java Compiler Compiler)mit dem Parser-Generator JavaCC (Java Compiler Compiler)

17

12 * x + 5 ...TOKEN: {| < PLUS: "+" >| < MINUS: "-" >}

void Addition():{ Token t = null;

StringBuilder sb = new StringBuilder();}{ Multiplikation()

( ( t = <PLUS> Multiplikation() ) { sb.append(t.ima ge); }| ( t = <MINUS> Multiplikation() ) { sb.append(t.im age); }

)*{ jjtThis.jjtSetValue(sb.toString()); }

}

5

+

*

x12

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

Regel 4: inkrementelle Entwicklung - Randbedingungen

18

package de.aoksystems.pragsys.service.pruefkern;

import de.aoksystems.pragsys.bo.statistik.Statistik;import de.aoksystems.pragsys.bo.pruefung.Pruefergebn is;

@Statelesspublic 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){...}

}

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

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

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

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-HandbuchRichtlinien-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

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

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 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

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

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-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

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

Beispiel: Code-Bereinigung mittels Checkstyle / Review

(5) Import-Organisation, Formatierung

(4) Namenskonventionen, Bezeichner, for

(3) JavaDoc, Anweisungs-Struktur, Kommentare

(2) try - catch , Parameterprüfung

23

(2) try - catch , Parameterprüfung

(1) Ausnahmebehandlung, Logging

� „Nice“

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

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 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

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

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-VerwaltungNutzung dedizierter Test-Datenbank(en)

explizite Testdaten-Erzeugung mittels Java (DBUnit, XMLUnit)

Schritt 3: Integrationstest der Service-Schichtper JUnit-Testclient gegen den Application-Server (remote)

mittels z. B. OpenEJB innerhalb der IDE (embedded)

Schritt 4: „automatisierter Abnahmetest“ der GUI-ClientsWerkzeug 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

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

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 /

26

(JUnit-Integration aller Werkzeuge / Frameworks vorausgesetzt)

� hierarchische Strukturierung der Test-Suites

� gesamte Test-Bibliothek auf Entwicklungsrechner lokal ausführbar

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

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ängelbeseitigungdirekte 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

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

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

28

� dadurch gleichzeitig Kapselung der Verwendung des JAXB-Framework

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

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-BibliothekMessung der Test-Überdeckung (Cobertura)Deployment auf QS-Umgebung (für manuelle Tests)

29