66
Ein Name ist ein name und kein String Jens Schumann open knowledge GmbH

Ein Name ist ein Name und kein String

Embed Size (px)

DESCRIPTION

Ist ein Geldbetrag vom Typ BigDecimal oder besser vom Typ Money? Ein Geburtstag? Date oder Birthday? Ein Vorname? String natürlich! Oder vielleicht doch Name? Interessanterweise wird in vielen Projekten die Verwendung einfacher Datentypen nie infrage gestellt. Zu selten, wie diese Session anhand von Java-SE-Beispielen und deren Verwendung in Java EE (JSF, JAX-WS/RS, JPA ...) eindrucksvoll zeigt.Speaker: Jens Schumann18.4.2012 | 16:15 - 17:15 Uhr | JAX, Mainz

Citation preview

Page 1: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

Jens Schumann

open knowledge GmbH

Page 2: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

In den nächsten 60 Minuten...

Page 3: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

In den nächsten 60 Minuten... ...gibt es nichts wesentlich Neues!

Bild via http://schnurpsel.de/neue-qualitaet-bei-kommentar-spam-oder-alter-hut-223/

Page 4: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

In den nächsten 60 Minuten...

Java und OO geht Java und OO macht Spaß

Page 5: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

Aber...

Page 6: Ein Name ist ein Name und kein String

OO in Java – Ein Kunde public class Customer { private String firstName; private String sureName; private Date birthDate; private Address address; ... } public class Address { private String zipCode; private String city; ... }

Page 7: Ein Name ist ein Name und kein String

OO in Java – eine Bestellung public class Order { private Customer customer; private String orderReference; private Date orderDate; private List<OrderEntry> entries; ... } public class OrderItem { private Item item; private double price; private int quantity; ... }

Page 8: Ein Name ist ein Name und kein String

OO in Java – eine Bestellung public class Order { private Customer customer; private String orderReference; private Date orderDate; private List<OrderEntry> entries; ... } public class OrderItem { private Item item; private double price; private int quantity; ... }

URKS

Page 9: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

Was für ein Anfänger! Geldbeträge als double!

Page 10: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

Ist das alles?!

Page 11: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda –  „OO in Java“ - As seen in the wild –  „OO in Java“ - Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java - Migrationspfad

Page 12: Ein Name ist ein Name und kein String

As seen in the wild: Anemic Domain public class Customer { private String firstName; private String sureName; private Date birthDate; private Address address; public void setFirstName(String firstName){...} public String getFirstName(...) public void setSureName(String sureName){...} public String getSureName(...) }

Fachlichkeit?

Page 13: Ein Name ist ein Name und kein String

As seen in the wild: Konstruktoren public class Customer { public Customer(String firstName, String sureName, String zipCode, String city) {} public Customer(String firstName, String sureName, String zipCode, String city, String street) {} }

Parameter?

Page 14: Ein Name ist ein Name und kein String

As seen in the wild: Validierung public class Customer { public Customer(String firstName, String sureName, String zipCode, String city) { Validate.true(StringUtils.notEmpty(firstName)); Validate.true(StringUtils.notEmpty(sureName)); ... } public void setFirstName(String aFirstName) { firstName = aFirstName; } }

Ups!

Page 15: Ein Name ist ein Name und kein String

As seen in the wild: Fachliche Validierung public class Customer { private static final String ZCODE_PATTERN = ...; public Customer(String firstName, String sureName, String zipCode, String city) { setFirstName(firstName); setZipCode(zipCode); ... } public void setZipCode(String zipCode){ Validate.true( Pattern.matches(ZCODE_PATTERN ,zipCode)); ... } }

Eigenschaft Customer?

Page 16: Ein Name ist ein Name und kein String

As seen in the wild: Konvertierung // Use Case: save new birthdate retrieved from web public void alterBirthDate(Customer customer, String newDate) { SimpleDateFormat df = new SimpleDateFormat(); Date birthDate = df.parse(newDate); Date today = new Date(); if (birthDate.after(today)){ ... } else { customer.setBirthDate(birtDate); } }

Ist das OO?

Page 17: Ein Name ist ein Name und kein String

As seen in the wild: Bewertung // has birthday today? Customer customer = ...; Calender todayCal = Calendar.getInstance(); Calender bdCal = Calendar.getInstance(); bdCal.setTime(customer.getBirthDate()); // validate year, month, date manually if (bdCal.get(Calendar.YEAR) >= todayCal.get(Calendar.YEAR)) { return false; } if (...) ...

Ist das OO?

Page 18: Ein Name ist ein Name und kein String

As seen in the wild: Utils & Helper public class BirthDateUtil { public static boolean hasBirthday(Date date) { ... } public static int getAge(Date date) { ... } } Customer cus = ...; if (BirthDateUtil.hasBirthday(cus.getBirthDate()){ }

Ist das OO?

Das gibt es?

Page 19: Ein Name ist ein Name und kein String

As seen in the wild: Immutability public class Customer { private Date birthDate; public void setBirthDate(Date newBirthDate) { if (isInFuture(newBirthDate)) {/* abort */} birthDate = newBirthDate; } public Date getBirthDate() { return birthDate; } } Customer cus = ...; cus.getBirthDate().setTime(...);

Validierung?

Page 20: Ein Name ist ein Name und kein String

As seen in the wild: API - talk to me public class CustomerDao { public List<Customer> findByZipCodeOrCity( String zipCode, String city) {...} public List<Customer> findByZipCodeOrCityLimit( String zipCode, String city, int limit) {...} public List<Customer> findByZipCodeOrCityAndOrders( String zipCode, String city, int orderCount) {...}

URKS

Page 21: Ein Name ist ein Name und kein String

As seen in the wild: API - talk to me public class CustomerDao { public List<Customer> findByZipCodeOrCity( String zipCode, String city) { } } public void searchMethod(...) { String current = ...; String value = ...; List<Customer> customers = dao.findByZipCodeOrCity(current, value); }

Hmmm..!?

Page 22: Ein Name ist ein Name und kein String

As seen in the wild: API Refactoring // Before public List<Customer> findByZipCodeOrCity( String zipCode, String city) {... } // After public List<Customer> findByZipCodeOrCity( String zipCode, String city, String street) {... }

Zum Glück haben wir JavaDoc!

Page 23: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda –  „OO in Java“ - As seen in the wild –  „OO in Java“ - Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java – Migrationspfad

Page 24: Ein Name ist ein Name und kein String

„OO in Java“ - Problemfelder

•  Domain Objekte ohne Fachlichkeit – Anemic Domain

•  Fachliche Objekte sind Value Objects mit einfachen Setter/Getter Methoden

– Fachlichkeit lebt außerhalb •  Konvertierung von Eigenschaften •  Validierung von Eigenschaften •  Konsistenzprüfung

Page 25: Ein Name ist ein Name und kein String

„OO in Java“ - Problemfelder

•  Null Value Value Handling – Null Value Handling erfolgt in den Use

Cases

Page 26: Ein Name ist ein Name und kein String

„OO in Java“ - Problemfelder

•  Duplicated Code – Konvertierung von Parametern – Validierung von Parametern – Validierung von Rückgabewerten

Page 27: Ein Name ist ein Name und kein String

„OO in Java“ - Problemfelder

•  Utils und Helper Inflation – Fachlichkeit und Domain sind weiterhin

getrennt –  „Ach wir haben dafür schon ein Util?“

•  Duplicated Code

Page 28: Ein Name ist ein Name und kein String

„OO in Java“ - Problemfelder

•  Keine „sprechenden“ Schnittstellen – Parameterhölle

•  Strings, Strings, Strings

– Methodennamen beschreiben Parameter – Keine Typsicherheit

Page 29: Ein Name ist ein Name und kein String

„OO in Java“ - Problemfelder

•  Robustheit – Refactoring erhöht Risiko

•  Programmierfehler •  Fehlerhafte API Methoden •  Fehlerhafte API Dokumentation

– Teamwachstum, Teamfluktuation •  Wo finde ich was? •  Wo gehört das hin?

Page 30: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda –  „OO in Java“ – As seen in the wild –  „OO in Java“ – Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java – Migrationspfad

Page 31: Ein Name ist ein Name und kein String

OO in Java

Konvention:

Ein Value Object repräsentiert

eine fachlich relevante Eigenschaft des Domain Modells.

Page 32: Ein Name ist ein Name und kein String

OO in Java - Regeln

#1: Value Objects sind Objekte – Eigenschaften sind nur in Ausnahmefällen

„primitiv“ public class Customer { private Date birthDate; }

X

Page 33: Ein Name ist ein Name und kein String

OO in Java - Regeln

#1: Value Objects sind Objekte – Eigenschaften sind nur in Ausnahmefällen

„primitiv“ public class Customer { private DateOfBirth dateOfBirth; }

Page 34: Ein Name ist ein Name und kein String

OO in Java - Regeln

#1: Value Objects sind Objekte – Eigenschaften sind nur in Ausnahmefällen

„primitiv“ public class DateOfBirth { private Date birthDate; public boolean hasBirthDay(); public int getCurrentAge(); }

Page 35: Ein Name ist ein Name und kein String

OO in Java - Regeln

#2: Value Objects sind immutable

public class DateOfBirth { private Date birthDate; public DateOfBirth(Date date) {...} public Date getDate() { return new Date(birthDate.getTime()); } }

Page 36: Ein Name ist ein Name und kein String

OO in Java - Regeln

#3: Value Objects konvertieren

public class DateOfBirth { public DateOfBirth(Date date) {...} public DateOfBirth(String date) {...} public DateOfBirth(String date, String pattern) {...} }

Page 37: Ein Name ist ein Name und kein String

OO in Java - Regeln

#4: Value Objects normalisieren

public class DateOfBirth { private Date birthDate; public DateOfBirth(Date date) { birthDate = copyAndStripTimestamp(date); } }

Page 38: Ein Name ist ein Name und kein String

OO in Java - Regeln

#5: Value Objects validieren fachlich

public class DateOfBirth { public DateOfBirth(Date date) { Date today = new Date(); if (date.after(today)) { throw new IllegalArgumentException( “Birthday “ + date + “ may not before current time “ + today); } ... } }

Page 39: Ein Name ist ein Name und kein String

OO in Java - Regeln

#6: Value Objects sind „vollwertig“ – Besitzen

•  equals •  hashCode •  toString

–  Implementieren in der Regel •  Serializable •  Comparable

Page 40: Ein Name ist ein Name und kein String

OO in Java - Regeln

Wo ist da die Grenze?

Page 41: Ein Name ist ein Name und kein String

OO in Java - Regeln

Zur Erinnerung:

Ein Value Object repräsentiert

eine fachlich relevante Eigenschaft des Domain Modells.

Page 42: Ein Name ist ein Name und kein String

OO in Java - Regeln

•  Typische Value Objects – FirstName, LastName, DateOfBirth – ZipCode, City, Country – Email, PhoneNumber – Note, Description – Year, Month, ... – Money,...

Page 43: Ein Name ist ein Name und kein String

OO in Java - Regeln

Konsequenzen

Page 44: Ein Name ist ein Name und kein String

True OO in Java - Konsequenzen

•  Fachlichkeit befindet sich in der Domain –  Inkl. Konvertierung, Validierung,

Normalisierung – Keine oder wenige Duplikate

•  „Sprechender“ Code List<Customer>

find(ZipCode code, City city); •  No more *Util, No more *Helper

Page 45: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda – OO in Java – As seen in the wild – OO in Java – Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java – Migrationspfad

Page 46: Ein Name ist ein Name und kein String

True OO in Java – was ein Quark!

•  Das muss doch langsam sein!

•  Fakten: – Java Objekterzeugung ist sehr günstig –  Immutability unterstützt Garbage Collector –  Immutability unterstützt inlining

Page 47: Ein Name ist ein Name und kein String

True OO in Java – was ein Quark!

•  Unsere Entwicklungsperformance! – Die Klassenexplosion! Nur unnützer Code!

•  Korrekt ist: – Domain Modell erfordert deutlich mehr

Vorarbeit – Speedup kommt im Projekt – Basisklassen helfen

Page 48: Ein Name ist ein Name und kein String

True OO in Java public abstract class SimpleValueObject<T extends Comparable> implements Serializable, Comparable<SimpleValueObject<T>> { private T value; public SimpleValueObject(T aValue) {...} protected T getValue() {...} public boolean equals(Object o) {...} public int hashCode() {...} public String toString() {...} public int compareTo(SimpleValueObject<T>o) {...}

Page 49: Ein Name ist ein Name und kein String

True OO in Java public class FirstName extends SimpleValueObject<String> { public FirstName(String aValue) { super(aValue); } public String getText() { return super.getValue(); } }

Page 50: Ein Name ist ein Name und kein String

True OO in Java – was ein Quark!

•  Da schreibt man sich die Finger wund!

// Vorher Customer customer = new Customer(“Max“,“Mustermann“); // Nacher Customer customer = new Customer(new FirstName(“Max“), new SureName(“Mustermann“);

Page 51: Ein Name ist ein Name und kein String

True OO in Java – was ein Quark!

•  Da schreibt man sich die Finger wund!

•  Fakten – Problem besteht an Systemgrenzen

•  Frameworks entschärfen Problem, dazu gleich mehr

– Problem besteht in Unit Tests •  Lösung: Erzeugung Testdaten zentralisieren

Page 52: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda – OO in Java – As seen in the wild – OO in Java – Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java – Migrationspfad

Page 53: Ein Name ist ein Name und kein String

True OO und JPA

•  Mapping von Value Objects – Binding via @Embeddable, @Embedded – Spaltendefinition über @Column oder

@AttributeOverride •  Value Objects und JPA-QL

– Navigation bis zu primitiven Eigenschaften •  Value Objects und Resultsets

– Nutzung in ScalarQueries

Page 54: Ein Name ist ein Name und kein String

True OO und JPA

•  True OO und JPA Mapping

@Embeddable public class DateOfBirth { @Column(name=“BIRTHDATE“) private Date date; } @Entity public class Customer { @Embedded private DateOfBirth dateOfBirth; }

Page 55: Ein Name ist ein Name und kein String

True OO und JPA

•  True OO und JPA AttributeOverrides

@Embeddable public class DateOfBirth { private Date date; } @Entity public class Customer { @Embedded @AttributeOverride(name=“date“, column=@Column(name=“BIRTHDATE“)) private DateOfBirth dateOfBirth; }

Page 56: Ein Name ist ein Name und kein String

True OO und JSF

•  Binding von Value Objects – Direkte Unterstützung durch Unified EL

•  Konvertierung von Value Objects – JSF Konverter

Page 57: Ein Name ist ein Name und kein String

True OO und JSF

•  Java Services Faces und GUI Binding

<h:outputText value=“#{customer.zipCode}“ /> <h:outputText value=“#{customer.dateOfBirth}“ /> <h:outputText value=“#{customer.dateOfBirth.date}“> <f:convertDateTime locale=“de" dateStyle="short" /> </h:outputText>

Page 58: Ein Name ist ein Name und kein String

True OO und JSF

•  Java Services Faces und Konvertierung

@FacesConverter(forClass = DateOfBirth.class) public class DateOfBirthConverter implements Converter { public Object getAsObject(..., String s)... { if (s == null ) { return null; } return new DateOfBirth(s); } }

Page 59: Ein Name ist ein Name und kein String

True OO und JSF

•  Java Services Faces und Konvertierung

@FacesConverter(forClass = DateOfBirth.class) public class DateOfBirthConverter implements Converter { public String getAsString(..., Object o) ...{ if (o != null) { return o.toString(); } return ""; } }

Page 60: Ein Name ist ein Name und kein String

True OO und JSF

•  Java Services Faces und Konvertierung

@Named public class CustomerController { public DateOfBirth getDateOfBirth() {} public void setDateofBirth(DateOfBirth dob) {} }

Page 61: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda – OO in Java – As seen in the wild – OO in Java – Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java – Migrationspfad

Page 62: Ein Name ist ein Name und kein String

True OO in Java - Migrationspfad

Ich starte aber nicht auf der grünen Wiese!

Page 63: Ein Name ist ein Name und kein String

True OO in Java - Migrationspfad

Refactoring ist dein Freund!

Page 64: Ein Name ist ein Name und kein String

Ein Name ist ein name und kein String

•  Agenda – OO in Java – As seen in the wild – OO in Java – Problemfelder – True OO in Java – True OO in Java - was ein Quark! – True OO in Java und Frameworks – True OO in Java – Migrationspfad

Page 65: Ein Name ist ein Name und kein String

Fazit

•  Fachlichkeit gehört IN Domain Modell –  „Primitive Datentypen“ vermeiden – Validierung, Konvertierung, Normalisierung

•  Einfache Kenngrößen beachten – Optimale Anzahl *Util: 0 ;) – Optimale Anzahl *Helper: 0 ;) – Optimale Länge Methodennamen: 20 ;)

•  Framework Features nutzen

Page 66: Ein Name ist ein Name und kein String