81

Click here to load reader

Mut zur Fachlichkeit

Embed Size (px)

DESCRIPTION

Mut zur Fachlichkeit Speaker: Lars Röwekamp Leider sind in der "freien Wildbahn" nach wie vor viele Architekturen und APIs stark durch die verwendeten Technologien, Frameworks, Generatoren etc. getrieben. Die eigentliche Fachlichkeit der Anwendung bleibt dabei häufig auf der Strecke und ist im Quellcode kaum noch auffindbar. Das geht – nur – solange gut, bis der erste Fehler gefunden werden muss. Die Session zeigt einfache, aber sehr effektive Strategien, wie bestehende Anwendungen in ein fachlich getriebenes Architektur- und API-Design überführt werden können - Aha-Effekte garantiert.

Citation preview

Page 1: Mut zur Fachlichkeit

@mobileLarson @_openKnowledge

Lars Röwekamp | CIO New Technologies

Mut zur Fachlichkeit

Page 2: Mut zur Fachlichkeit

Business vs. Technology Mut zur Fachlichkeit

JAX2014

„May I submit my billing info to your merchant account via your payment

gateway?“

Page 3: Mut zur Fachlichkeit

Mut zur FachlichkeitJAX2014

End User

Domain Expert

TechnicalExpert

Business vs. Technology

Translationist auf Dauer teuer - sogar sehr teuer!

Page 4: Mut zur Fachlichkeit

Mut zur FachlichkeitJAX2014

End User

Domain Expert

TechnicalExpert

Ubiquitous Language

Basis für ein konsistentes

Domain Model

Business vs. Technology

Page 5: Mut zur Fachlichkeit

„Produce Software that makes perfectly sense to business,

not only to coder“

Mut zur FachlichkeitJAX2014

End User

Domain Expert

TechnicalExpert

Rich Domain Model

Business vs. Technology

Page 6: Mut zur Fachlichkeit

„Produce Software that is always

in a correct state, not only partially“

Mut zur FachlichkeitJAX2014

Domain Expert

TechnicalExpert

Rich Domain Model

Business vs. Technology

Access Layer

Business Layer

DB Layer

Page 7: Mut zur Fachlichkeit

Mut zur FachlichkeitReality CheckJAX

2014

Page 8: Mut zur Fachlichkeit

Mut zur FachlichkeitReality CheckJAX

2014

The déjà-vuExperiment

Page 9: Mut zur Fachlichkeit

/** * Represents a business customer with a * full qualified name, a date of birth indicating * if the customer is „sui juris“ and a valid address * that may change after a relocation. */ public class Customer { ! private String firstName; private String sureName; ! private Date birthDate; private Address address; ! public void setFirstName(String aFirstName) { ... } public String getFirstName() { return firstName; } ! public void setSureName(String aSureName) { ... } public String getSureName() { return sureName; } ! public void setBirthDate(Date birthDate) { ... } public Date getBirthDate() { return birthDate; } ! public void setAddress(Address address) { ... } public Address getAddress() { return address; } !}

Reality Check

Fachlichkeit?

JAX2014 Mut zur Fachlichkeit

Page 10: Mut zur Fachlichkeit

/** * Represents a business customer with a * full qualified name, a date of birth indicating * if the customer is „sui juris“ and a valid address * that may change after a relocation. */ 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) { ... } ... }

Reality Check

Parameter (Hölle)?

JAX2014 Mut zur Fachlichkeit

Konstruktor (Hölle)?

Page 11: Mut zur Fachlichkeit

/** * Represents a business customer with a * full qualified name, a date of birth indicating * if the customer is „sui juris“ and a valid address * that may change after a relocation. */ public class Customer { ! public Customer(String firstName, String sureName, String zipCode, String city) { Validate.isTrue(StringUtils.isNotEmpty(firstName)); Validate.isTrue(StringUtils.isNotEmpty(sureName)); ... } ! public void setFirstName(String firstName) { this.firstName = firstName; } !! ... }

Reality CheckJAX2014 Mut zur Fachlichkeit

Validierung?

Page 12: Mut zur Fachlichkeit

/** * Represents a business customer with a * full qualified name, a date of birth indicating * if the customer is „sui juris“ and a valid address * that may change after a relocation. */ 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.isTrue(Pattern.matches(ZCODE_PATTERN, zipCode)); } ! ... }

Reality CheckJAX2014 Mut zur Fachlichkeit

Richtig hier?

Page 13: Mut zur Fachlichkeit

/** * Represents a controller to handle * customer related changes */ public class CustomerController { !/** * save new date of birth retrieved from the web * in a customer entity */ public void alterBirthDate(Customer customer, String newDate) { ! SimpleDateFormat df = new SimpleDateFormat(); Date birthDate = null; try { birthDate = df.parse(newDate); } catch (ParseException e) { // do something } Date today = new Date(); ! if (birthDate.after(today)) { // do something } else { customer.setBirthDate(birthDate); } } ... }

Reality CheckJAX2014 Mut zur Fachlichkeit

Konvertierung?

Page 14: Mut zur Fachlichkeit

/** * Represents a controller to handle * customer related changes */ public class CustomerController { ! /** * check if a customer has birthday today */ public boolean hasBirthDay(Customer customer) { ! Calendar todayCal = Calendar.getInstance(); Calendar birthDateCal = Calendar.getInstance(); birthDate.setTime(customer.getBirthDate().getTime()); ! if (birthDateCal.get(Calendar.YEAR) > (todayCal.get(Calendar.YEAR))) { return false; } else if (birthDateCal.get(Calendar.MONTH) != (todayCal.get(Calendar.MONTH))) { return false; } else if (birthDateCal.get(Calendar.DAY_OF_MONTH) != (todayCal .get(Calendar.DAY_OF_MONTH))) { return false; } return true; } ... }

Reality CheckJAX2014 Mut zur Fachlichkeit

Auswertung?

Page 15: Mut zur Fachlichkeit

/** * Util to calculate current age for a given date * and to calculate if the date is a birthday today. */ public class BirthDayUtilAkaHelper { public static boolean hasBirthDay(Date date) { ... return ...; } public static int getAge(Date date) { return 0; } } !/** * usage of BirthdayUtil */ Customer customer = ...; if (BirthDayUtilAkaHelper.hasBirthDay(customer.getBirthDate())) { ...; }

Reality CheckJAX2014 Mut zur Fachlichkeit

Util & Helper (Hölle)?

Manager?

Page 16: Mut zur Fachlichkeit

/** * Represents a business customer with a * full qualified name, a date of birth indicating * if the customer is „sui juris“ and a valid address * that may change after a relocation. */ public class Customer { ! private Date birthDate; ! public void setBirthDate(Date newBirthDate) { if (isInFuture(newBirthDate)) { /*abort */ ... } birthDate = newBirthDate; } ! public Date getBirthDate() { return birthDate; } ... } !/** * usage of getBirthDate */ Customer customer = ...; customer.getBirthDate().setTime(someTimeInFuture);

Reality Check

Immutable?

JAX2014 Mut zur Fachlichkeit

Page 17: Mut zur Fachlichkeit

/** * Data Access Object for retrieving * customer objects from the DB. */ public class CustomerDao { ! public List<Customer> findByZipCodeOrCity(String zipCode, String city) { return ...; } ! public List<Customer> findByZipCodeOrCityWithLimit(String zipCode, String city, int limit) { return ...; } ! public List<Customer> findByZipCodeOrCityAndOrders(String zipCode, String city, int orderCount) { return ...; } } !/** * usage of getBirthDate */ String current= ...; String value = ...; List<Customer> searchResult = dao.findByZipCodeOrCity(current,value);

Reality Check

Meaningful API?

JAX2014 Mut zur Fachlichkeit

Correct Order?

Page 18: Mut zur Fachlichkeit

/** * Data Access Object for retrieving * customer objects from the DB. */ public class CustomerDao { // BEFORE refactoring public List<Customer> findByZipCodeOrCity(String zipCode, String city) { return ...; } ! // AFTER refactoring public List<Customer> findByZipCodeOrCity(String zipCode, String city, String street) { return ...; } ! ...; }

Reality Check

Refactoring?

JAX2014 Mut zur Fachlichkeit

Page 19: Mut zur Fachlichkeit

Mut zur FachlichkeitProblemfelderJAX

2014

Page 20: Mut zur Fachlichkeit

JAX2014

Anemic Domain Model !

„Pay most of the high cost of developing a Domain Model, but get little or none of the benefits.“

Mut zur FachlichkeitProblemfelder

(Vaugn Vernon, Implementing Domain-Driven Design)

Page 21: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Anemic Domain Model !

‣ „kraftloses“ fachliche Objekte mit getter/setter ‣ eigentliche Fachlichkeit ausserhalb des Modells !

‣ Konsistenzprüfung ausserhalb ‣ Konvertierung ausserhalb ‣ Validierung ausserhalb

Page 22: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Anemic Domain Model !

‣ forced by procedural programming mentality ‣ forced by oversimplified samples !

‣ forced by Tool-Support ‣ forced by generated Models ‣ forced by Specifications

Page 23: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Anemic Domain Model

1980s 1991 1992-1995 1996/1997 1998+

Objekte gewinnen an Bedeutung dank C++ und Smalltalk

Visuelle Tools und IDEs werden „produktiv“ und verbreiten sich

„Explosion“ von Reflexion-basierten Tools und Frameworks

Visual Basic Properties und Property Sheets erscheinen

Release von Java JDK 1.0 und der JavaBeans Spezifikation

Page 24: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Anemic Domain Model !

‣ Besitzt „Domain Model“ hauptsächlich getter/setter, kaum Business Logik undfungiert als Attribute-Holder? !

‣ Sitzt die Business Logik in den Nutzern des „Domain Models“ und ruft dort getter/setter auf?

Page 25: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Null Value Handling !

‣ wird validiert? ‣ wann wird validiert? ‣ wie oft wird validiert? !

‣… und vor allem wo wird validiert? ‣… bitte nicht in den Use Cases!

Page 26: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Duplicated Code !

‣ Konvertierung von Parametern ‣ Validierung von Parametern ‣ Validierung von Rückgabewerten

Page 27: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Utils & Helper (und Manager und …) !

‣ Verlagerung des Problems ‣ Trennung von Fachlichkeit & Domain !

‣ Util Hell a.k.a. „Ach wir haben dafür ein Util?“ ‣ Code Duplication als Konsequenz

Page 28: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Non-Meaningful APIs !

‣ String & Friends Parameter Hölle ‣ fehlende Typsicherheit !

‣Methodennamen als Parameter-Deskriptor ‣Methodennamen als Refactoring-Pitfall

Page 29: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Fehlende Robustheit !

‣ Refactoring erhöht das Risiko für … ‣… Programmierfehler ‣… fehlerhafte API Methoden ‣… fehlerhafte API Dokumentation

Page 30: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Problemfelder

Fehlende Robustheit !

‣ Teamwachstum / -fluktuation als Risiko ‣Wo finde ich was? ‣Was macht das? ‣Wo gehört das hin? !

‣ Copy & Paste Design Pattern!

Page 31: Mut zur Fachlichkeit

Mut zur FachlichkeitLösungsansätzeJAX

2014

Page 32: Mut zur Fachlichkeit

JAX2014

Zur Erinnerung !

„Wir möchten ein sprechendes Domain Model, mit einem sprechenden API, welches wir in sich konsistent erzeugen und im weiteren Verlauf konsequent konsistent erhalten.“

Mut zur FachlichkeitLösungsansätze

Page 33: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Lösungsansätze

Anforderungen !

‣ sprechendes Modell ‣ sprechendes API !

‣ konsistent erzeugen ‣ konsistent erhalten

Page 34: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Lösungsansätze

Rich Domain Model !

‣ inkl. Fachlichkeit ‣ inkl. Validierung ‣ inkl. Konvertierung ‣ inkl. Normalisierung ‣ inkl. Konsistenzprüfung

Page 35: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Lösungsansätze

Refactoring Step by Step !

‣ Schritt 1: Value Objects ‣ Schritt 2: Builder Pattern ‣ Schritt 3: Framework Support

Page 36: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Page 37: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects Definition !

‣ Ein Value Object repräsentiert eine fachlich relevante Eigenschaft des Domain Models.

Wo ist da die Grenze?

Page 38: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects Definition !

‣ Ein Value Object repräsentiert eine fachlich relevante Eigenschaft des Domain Models.

Page 39: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects … !

‣ #1: sind Objekte und keine primitive ‣ #2: sind unveränderbar ‣ #3: konvertieren fachlich ‣ #4: normalisieren fachlich ‣ #5: validieren fachlich ‣ #6: sind vollwertig und vergleichbar !

Page 40: Mut zur Fachlichkeit

/** * #1: Value Objects sind Objekte */ public class Customer { ! private Date birthDate; ! private DateOfBirth birthDate; ! ... !) !/** * Represents a date of birth */ public class DateOfBirth { ! private Date dateOfBirth; ! public boolean hasBirthDay() { return ...; } ! public int getCurrentAge() { return ...; } }

Schritt 1: Value Objects

Fachlichkeit!

JAX2014 Mut zur Fachlichkeit

Page 41: Mut zur Fachlichkeit

/** * #2: Value Objects sind unveränderbar */ public class DateOfBirth { ! private Date dateOfBirth; public DateOfBirth(Date date) { // do some validation here and // throw IllegalArgumentException if fail ...; this.dateOfBirth = date; } public Date getDate() { return new Date(dateOfBirth.getTime()); } ! public boolean hasBirthDay() { return ...; } ! public int getCurrentAge() { return ...; } !}

Schritt 1: Value Objects

Immutable!

JAX2014 Mut zur Fachlichkeit

Page 42: Mut zur Fachlichkeit

/** * #3: Value Objects konvertieren fachlich */ public class DateOfBirth { ! private Date dateOfBirth; public DateOfBirth(Date date) { // do some validation here and // throw IllegalArgumentException if fail ...; this.dateOfBirth = date; } public DateOfBirth(String date) { // create date of birth from "date" string with default pattern ...; ! } public DateOfBirth(String date, String pattern) { // create date of birth from "date" string with "pattern" ...; } ! ... !}

Schritt 1: Value Objects

Konvertieren!

JAX2014 Mut zur Fachlichkeit

Page 43: Mut zur Fachlichkeit

/** * #4: Value Objects normalisieren fachlich */ public class DateOfBirth { ! private Date dateOfBirth; public DateOfBirth(Date date) { // do some validation here and // throw IllegalArgumentException if fail ...; this.dateOfBirth = copyAndStripTimeStamp(date); } private Date copyAndStripTimeStamp(Date date) { // strip timestamp and copy result in a new Date object return ...; ! } ... !}

Schritt 1: Value Objects

Normalisieren!

JAX2014 Mut zur Fachlichkeit

Page 44: Mut zur Fachlichkeit

/** * #4: Value Objects validieren fachlich */ public class DateOfBirth { ! private Date dateOfBirth; public DateOfBirth(Date date) { Date today = new Date(); if (date.after(today)) { throw new IllegalArgumentException("Birthday " + date + " may not be after current time " + today); } this.dateOfBirth = copyAndStripTimeStamp(date); } private Date copyAndStripTimeStamp(Date date) { // strip timestamp and copy result in a new Date object return ...; ! } ... !}

Schritt 1: Value Objects

Validieren!

JAX2014 Mut zur Fachlichkeit

Page 45: Mut zur Fachlichkeit

/** * #4: Value Objects sind vollwertig */ public class DateOfBirth implements Serializable, Comparable{ ! private Date dateOfBirth; ... ! @Override public String toString() { return ...; } ! @Override public int hashCode() { return ...; } ! @Override public boolean equals(Object obj) { return ...; } ! public int compareTo(Object o) { return ...; }}

Schritt 1: Value Objects

Full blown Object!

JAX2014 Mut zur Fachlichkeit

Page 46: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects Beispiele !

‣ FirstName, LastName, DateOfBirth ‣ ZipCode, City, Country ‣ Email, PhoneNumber ‣ Note, Description ‣ Year, Month, … !

‣Money, …

Page 47: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects Benefits !

‣ Fachlichkeit befindet sich direkt in der Domain ‣ Kein/kaum duplizierter Code !

‣ sprechender & konsistenter Code ‣ verbesserter Lesbarkeit & Wartbarkeit !

‣ Keine Util, Helper, Manager & Friends

Page 48: Mut zur Fachlichkeit

// Entity with Value Objects public class Customer { private FirstName firstName; private LastName lastName; private FamilyStatus familyStatus; private Address postalAddress; private HashMap<PhoneNumber> phoneNumbers; private HashMap<EmailAddress> emailAddresses; ... public void changePersonalName(FirstName newFirstName, LastName newLastName) { ... } public void relocatePostalAddress(Address changedPostalAddress) { ... } public void changeHomePhoneNumber(PhoneNumber changedHomePhoneNumber) { ... } public void disconnectHomePhone() { ...} public void changeMobilePhoneNumber(PhoneNumber changedHomePhoneNumber) { ... } public void disconnectMobilePhone() { ... } public void changePrimaryEmailAddress(EmailAddress newPrimaryEmailAddress) { ... } public void changeSecondaryEmailAddress(EmailAddress newSecondaryEmailAddress) { ... } ! public List<Email> findEmailsOf(EmailDomain emailDomain) { ... } ! public void marry(LastName newLastName) { lastName = newLastName familyStatus = FamilyStatus.MARRIED; } public boolean isMarried() { return (familyStatus == FamilyStatus.MARRIED); } }

Schritt 1: Value Objects JAX2014 Mut zur Fachlichkeit

Page 49: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 2: Builder Pattern

Page 50: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 2: Builder Pattern

Das kleine 1x1 des Builder Pattern !

‣ Object Creation Design Pattern ‣ Antwort auf das Constructor-Hell Anti-Pattern !

‣ Step-by-Step Ansatz ‣ Kandidat für Fluent-API

Page 51: Mut zur Fachlichkeit

// Builder Pattern - Poor Mans Edition public class Address { ! public Address(String street, String streetNumber, String zipCode, String city, String state, String country) { Validate.isTrue(StringUtils.isNotEmpty(streetNumber)); Validate.isTrue(StringUtils.isNotEmpty(zipCode)); Validate.isTrue(StringUtils.isNotEmpty(city)); Validate.isTrue(StringUtils.isNotEmpty(state)); Validate.isTrue(StringUtils.isNotEmpty(country)); ... } ! // value object is immutable // - no setter // - but getter ...; }

Schritt 2: Builder PatternJAX2014 Mut zur Fachlichkeit

Schön? Nee!

Page 52: Mut zur Fachlichkeit

// Builder Pattern - Simple Edition public class AddressBuilder { private Street street; private StreetNumber streetNumber; private ZipCode zipCode; private City city; private State state; private Country country; public Address build() { // validate single parameter and cross parameter constraints // and throw exception if any problem occurs ... // create valid Address object else return new Address(...); } public void setStreet(Street street) { this.street = street; } ! public void setStreetNumber(StreetNumber streetNumber) { this.streetNumber = streetNumber; } ! ... }

Schritt 2: Builder PatternJAX2014 Mut zur Fachlichkeit

Schöner? Naja!

Page 53: Mut zur Fachlichkeit

// Builder Pattern - Simple Edition IN ACTION !// create AddressBuilder AddressBuilder builder = new AddressBuilder(); !// set all known values // BTW: could be also used in JSF and other frameworks builder.setStreet(...); builder.setStreetNumber(...); builder.setZipCode(...); builder.setCity(...); builder.setState(...); builder.setCountry(...); !// build valid and immutable Address object Address address = builder.build();

Schritt 2: Builder PatternJAX2014 Mut zur Fachlichkeit

Page 54: Mut zur Fachlichkeit

// Builder Pattern - Extended Edition public class AddressBuilder { private Street street; private StreetNumber streetNumber; ... private AddressBuilder() { /* empty constructor to prohibit use */ } public static AddressBuilder newAddress() { return new AddressBuilder(); } public AddressBuilder forStreetNumber(StreetNumber aStreetNumber) { streetNumber = aStreetNumber; } public AddressBuilder ofStreet(Street aStreet) { street = aStreet; } public Address build() { // validate single parameter and cross parameter constraints // and throw exception if any problem occurs ... // create valid Address object else return new Address(...); } }

Schritt 2: Builder PatternJAX2014 Mut zur Fachlichkeit

Schöner? Ja!

Page 55: Mut zur Fachlichkeit

// Builder Pattern - Extended Edition IN ACTION !// create AddressBuilder AddressBuilder builder = newAddress() ! // set values .forStreetNumber(...).ofStreet(...) .inCity(...).withZipCode(...) .lyingInState(...).ofCountry(...) ! // build Address object .build(...);

Schritt 2: Builder PatternJAX2014 Mut zur Fachlichkeit

Page 56: Mut zur Fachlichkeit

// Builder Pattern - Extended Edition with Inner Class Builder public class Address { ! public static Builder newAddress() { return new Address().new Builder(); } ! private String street; ! public class Builder { ! public Builder ofStreet(String initialStreet) { street = validateStreet(initialStreet); return this; } ! public Address build() { validate(); return Address.this; } } }

Schritt 2: Builder PatternJAX2014 Mut zur Fachlichkeit

Page 57: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 58: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

JSF?Access Layer

Business Layer

DB Layer JPA?

jUnit?

Page 59: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Value Objects & JPA !

‣ Value Objects und Mapping ‣ Binding via @Embeddable / @Embedded ‣ Spaltendef. via @Column / @AttributeOverride ‣ Value Objects und JPA-QL ‣ Navigation bis zu primitiven Eigenschaften ‣ Value Objects und ResultSet ‣ via ScalarQueries

Schritt 3: Framework Support

Page 60: Mut zur Fachlichkeit

/** * Embeddable date of birth for (re)use in value objects */ @Embeddable public class DateOfBirth { ! @Column(name=“BIRTHDATE“) // use this or … private Date dateOfBirth; ! ... } !!/** * Customer entity making use of date of birth embeddable */ @Entity public class Customer { ! @Embedded @AttributeOverride(name=„dateOfBirth", // … this column=@Column(name=“CUST_BIRTHDATE“)) // … or both private DateOfBirth dateOfBirth; ! ... }

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 61: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Value Objects & JPA !

‣ Value Objects und JPA-QL ‣ Navigation bis zu Value Objects ‣ Navigation bis zu primitiven Eigenschaften

Schritt 3: Framework Support

Page 62: Mut zur Fachlichkeit

/** * Using JPA-QL and ValueObjects */ @Entity @Table(name = "TAB_USER", ...) @NamedQueries({ @NamedQuery(name = "User.findByEmail", query = "select u from User u where u.email = :email"), @NamedQuery(name = "User.findByEmailString", query = "select u from User u where u.email.value = :emailString“) }) public class User extends AbstractEntity { ! protected static final String EMAIL_COLUMN = "EMAIL"; ! @AttributeOverride(name = "value", column = @Column(name = EMAIL_COLUMN, unique = true, nullable = false)) private Email email; ! ... !}

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 63: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Value Objects & JPA !

‣ Value Objects und ResultSet ‣ via ScalarQueries

Schritt 3: Framework Support

Page 64: Mut zur Fachlichkeit

/** * Examples for ResultSets and ValueObjects (via ScalarQueries) */ public FullNameWithAddress findFullNameWithAddress(Email uniqueEmail) { TypedQuery<Object[]> query = em.createQuery( "SELECT c.name, c.address from Customer c "‚ + "WHERE u.email.value = :emailString"‚ Object[].class); query.setParameter("emailString", uniqueEmail.getAddress()); ! Object[] result = query.getSingleResult(); FullName fullName = (FullName) result[0]; Address address = (Address) result[1]; return new FullNameWithAddress(fullName, address); } !public List<FullNameWithAddress> findFullNamesWithAddress() { ! TypedQuery<FullNameWithAddress> query = em.createQuery( "SELECT " + " new de.openknowlede.FullNameWithAddress(c.name, c.address) " + " from Customer c", FullNameWithAddress.class ); return query.getResultList(); }

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 65: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Value Objects & JSF !

‣ Binding von Value Objects ‣ direkte Unterstützung durch U-EL ‣ Konvertierung von Value Objects ‣ via JSF Converter ‣ Validierung von Value Objects ‣ via JSF Validator

Schritt 3: Framework Support

Page 66: Mut zur Fachlichkeit

/** CDI based JSF Controller managing * user related input */ @Named("customerController") @RequestScoped public class CustomerController { private DateOfBirth dateOfBirth; private ZipCode zipCode; ...; public DateOfBirth getDateOfBirth() { return dateOfBirth; } ! public void setDateOfBirth(DateOfBirth newDateOfBirth) { dateOfBirth = newDateOfBirth; } public ZipCode getZipCode() { return zipCode; } ! public void setZipCode(ZipCode newZipCode) { zipCode = newZipCode; } ... }

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 67: Mut zur Fachlichkeit

<!-- Value Object binding in JSF xhtml page via Unified Expression Language & JSF Faces Converter --> !<!-- using JSF converter for Value Object of type ZipCode --> <h:outputText value=“#{customerController.zipCode}“ /> !<h:outputText value=“#{customerController.zipCode}“ > <f:converter converterId=“de.openknowledge.jsf.converter.ZipCodeConverter“ </h:outputText> !!<!-- using JSF converter for Value Object of type DateOfBirth --> <h:outputText value=“#{customerController.dateOfBirth}“ /> !<h:outputText value=“#{customerController.dateOfBirth}“ > <f:converter converterId=“de.openknowledge.jsf.converter.DateOfBirthConverter“ </h:outputText> !<!-- using JSF default converter for Date & Time objects --> <h:outputText value=“customerController.dateOfBirth.date“ > <f:convertDateTime locale=“DE“ dateStyle=“short“/> </h:outputText>

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 68: Mut zur Fachlichkeit

@FacesConverter(forClass = DateOfBirth.class, value = "de.openknowledge.jsf.converter.DateOfBirthConverter") public class DateOfBirthConverter implements Converter { // convert String input into Value Object @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value == null) { return null; } return new DateOfBirth(value); } // convert Value Object into String @Override public String getAsString(FacesContext context, UIComponent component, Object value) { String string = null; // power point programming - not bullet proofed! if (value!=null) { string = value.toString(); } return string; } }

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

Page 69: Mut zur Fachlichkeit

Mut zur FachlichkeitKritiker zu WortJAX

2014

Page 70: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Kritiker zu Wort

Das soll funktionieren? Das … !

‣… ist doch viel zu langsam! ‣… sind doch viel zu viele Klassen! ‣… ist doch viel zu aufwendig!

Page 71: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Kritiker zu Wort

Das ist doch viel zu langsam! !

‣ Java Objekterzeugung ist nicht mehr teuer ‣ Immutability unterstützt Garbage Collection ‣ Immutability unterstützt Inlining

Page 72: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Kritiker zu Wort

Das sind doch viel zu viele Klassen! !

‣ Domain Model erfordert mehr Vorarbeit ‣ Speedup kommt später im Projekt !

‣ deutlich bessere Verständnis für die Domain ‣ deutlich bessere Entwicklungsperformance !

‣ Basisklassen helfen

Page 73: Mut zur Fachlichkeit

/** * Abstract value object as a common base for all single value * value objects. */ public abstract class SimpleValueObject<T extends Comparable> implements Serializable, Comparable<SimpleValueObject<T>> { ! private T value; ! public SimpleValueObject(T aValue) { value = aValue; } ! protected T getValue() { return value; } ! public boolean equals(Object o) { return ...; } ! public int hashCode() { return ...; } ! public String toString() { return ...; } ! public int compareTo(SimpleValueObject<T> o) { return ...; } }

Kritiker zu WortJAX2014 Mut zur Fachlichkeit

Page 74: Mut zur Fachlichkeit

/** * Simple value object for first name using the * common base <code>SimpleValueObject</code> */ public class FirstName extends SimpleValueObject<String> { ! public FirstName(String aValue) { super(aValue); } ! public String getText() { return super.getValue(); } !}

Kritiker zu WortJAX2014 Mut zur Fachlichkeit

Page 75: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Kritiker zu Wort

Das ist doch in der Nutzung viel zu aufwendig! !

‣ komplexe Konstruktoren, da Typen statt „String“ ‣ komplexe API aufrufe, da Typen statt „String“!// Vorher Customer customer = new Customer(“Max“,“Mustermann“); !// Nacher Customer customer = new Customer(new FirstName(“Max“), new SureName(“Mustermann“);

Page 76: Mut zur Fachlichkeit

JAX2014 Mut zur Fachlichkeit

Kritiker zu Wort

Das ist doch viel zu aufwendig! !

‣ Problemfeld „Konstruktoren“ ‣ Builder Pattern ‣ Problemfeld „Systemgrenzen“ ‣ Frameworks entschärfen das Problem ‣ Problem „Unit Test“ ‣ zentralisierte Erzeugung von Testdaten

Page 77: Mut zur Fachlichkeit

Mut zur FachlichkeitFazitJAX

2014

Page 78: Mut zur Fachlichkeit

JAX2014

!!

„The Design is the Code, the Code is the Design.“

Mut zur FachlichkeitFazit

Page 79: Mut zur Fachlichkeit

JAX2014

„Muss ich denn jedes Mal den Code ändern, wenn

sich die Fachlichkeit ändert?“

Mut zur FachlichkeitFazit

Page 80: Mut zur Fachlichkeit

JAX2014

„Zur Hölle, ja! !

Wann denn bitte sonst?“

Mut zur FachlichkeitFazit

Page 81: Mut zur Fachlichkeit

@mobileLarson @_openKnowledge

Lars Röwekamp | CIO New Technologies

Mut zur Fachlichkeit

lohnt sich!