Business vstechnology

Post on 23-Jun-2015

122 views 2 download

Transcript of Business vstechnology

@mobileLarson @_openKnowledge

Lars Röwekamp | CIO New Technologies

Mut zur Fachlichkeit

Business vs. Technology Mut zur Fachlichkeit

JAX2014

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

gateway?“

Mut zur FachlichkeitJAX2014

End User

Domain Expert

TechnicalExpert

Business vs. Technology

Translationist auf Dauer teuer - sogar sehr teuer!

Mut zur FachlichkeitJAX2014

End User

Domain Expert

TechnicalExpert

Ubiquitous Language

Basis für ein konsistentes

Domain Model

Business vs. Technology

„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

„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

Mut zur FachlichkeitReality CheckJAX

2014

Mut zur FachlichkeitReality CheckJAX

2014

The déjà-vuExperiment

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

/** * 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)?

/** * 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?

/** * 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?

/** * 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?

/** * 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?

/** * 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?

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

/** * 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?

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

Mut zur FachlichkeitProblemfelderJAX

2014

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)

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

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

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

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?

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!

JAX2014 Mut zur Fachlichkeit

Problemfelder

Duplicated Code !

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

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

JAX2014 Mut zur Fachlichkeit

Problemfelder

Non-Meaningful APIs !

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

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

JAX2014 Mut zur Fachlichkeit

Problemfelder

Fehlende Robustheit !

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

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!

Mut zur FachlichkeitLösungsansätzeJAX

2014

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

JAX2014 Mut zur Fachlichkeit

Lösungsansätze

Anforderungen !

‣ sprechendes Modell ‣ sprechendes API !

‣ konsistent erzeugen ‣ konsistent erhalten

JAX2014 Mut zur Fachlichkeit

Lösungsansätze

Rich Domain Model !

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

JAX2014 Mut zur Fachlichkeit

Lösungsansätze

Refactoring Step by Step !

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

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

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?

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects Definition !

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

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 !

/** * #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

/** * #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

/** * #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

/** * #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

/** * #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

/** * #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

JAX2014 Mut zur Fachlichkeit

Schritt 1: Value Objects

Value Objects Beispiele !

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

‣Money, …

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

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

JAX2014 Mut zur Fachlichkeit

Schritt 2: Builder Pattern

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

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

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

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

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

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

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

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

JAX2014 Mut zur Fachlichkeit

Schritt 3: Framework Support

JSF?Access Layer

Business Layer

DB Layer JPA?

jUnit?

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

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

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

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

JAX2014 Mut zur Fachlichkeit

Value Objects & JPA !

‣ Value Objects und ResultSet ‣ via ScalarQueries

Schritt 3: Framework Support

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

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

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

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

@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

Mut zur FachlichkeitKritiker zu WortJAX

2014

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!

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

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

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

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

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

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

Mut zur FachlichkeitFazitJAX

2014

JAX2014

!!

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

Mut zur FachlichkeitFazit

JAX2014

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

sich die Fachlichkeit ändert?“

Mut zur FachlichkeitFazit

JAX2014

„Zur Hölle, ja! !

Wann denn bitte sonst?“

Mut zur FachlichkeitFazit

@mobileLarson @_openKnowledge

Lars Röwekamp | CIO New Technologies

Mut zur Fachlichkeit

lohnt sich!