SlideShare ist ein Scribd-Unternehmen logo
1 von 60
@mobileLarson 

@_openKnowledge
Lars Röwekamp
CIO New Technologies
The Courage to Business Logic

#WISSENTEILEN
Business vs. Technology
The Courage to Business Logic
Voxxed
Days
„May I submit my billing info 

to your merchant account 

via your payment gateway?“
offenkundiggut #WISSENTEILEN
Business vs. Technology
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
End User
Domain 

Expert
Technical

Expert
Ubiquitous Language
„Common language as the
basis for a consistent
domain model.“
Business vs. Technology
Voxxed
Days
offenkundiggut #WISSENTEILEN
„Produce Software 

that makes perfectly 

sense to business, 

not only to coder“
The Courage to Business Logic
End User
Domain 

Expert
Technical

Expert
Rich Domain Model
Business vs. Technology
Voxxed
Days
offenkundiggut #WISSENTEILEN
„Produce Software 

that is always 

in a correct state, 

not only partially“
The Courage to Business Logic
Domain 

Expert
Technical

Expert
Rich Domain Model
Business vs. Technology
Access Layer
Business Layer
DB Layer
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Reality Check
The déjà-vu

Experiment
Voxxed
Days
offenkundiggut #WISSENTEILEN
offenkundiggut #WISSENTEILEN
/**
* 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 lastName;
private Date birthDate;
private Address address;
public void setFirstName(String aFirstName) { ... }
public String getFirstName() { return firstName; }
public void setLastName(String aLastName) { ... }
public String getLastName() { return lastName; }
public void setBirthDate(Date birthDate) { ... }
public Date getBirthDate() { return birthDate; }
public void setAddress(Address address) { ... }
public Address getAddress() { return address; }
}
Reality Check
„Business“ Logic?
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 lastName,
String zipCode,
String city) { ... }
public Customer(String firstName,
String lastName,
String zipCode,
String city,
String street) { ... }
...
}
Reality Check
Parameter (Hell)?
The Courage to Business Logic
Constructor (Hell)?
Voxxed
Days
offenkundiggut #WISSENTEILEN
Reality Check
The Courage to Business Logic
/**
* 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,
String,
String,
String) { ... }
public Customer(String,
String,
String,
String,
String) { ... }
...
}
„no-Sources“ View
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 lastName,
String zipCode,
String city) {
Validate.isTrue(StringUtils.isNotEmpty(firstName));
Validate.isTrue(StringUtils.isNotEmpty(sureName));
...
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
...
}
Reality Check
The Courage to Business Logic
Validation?
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 ZIP_CODE_PATTERN = ...;
public Customer(String firstName,
String sureName,
String zipCode,
String city) {
setFirstName(firstName);
setZipCode(zipCode);
...
}
public void setZipCode(String zipCode) {
Validate.isTrue(Pattern.matches(ZIP_CODE_PATTERN, zipCode));
}
...
}
Reality Check
The Courage to Business Logic
Right place?
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 Check
The Courage to Business Logic
Conversion?
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 Check
The Courage to Business Logic
Evaluation?
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 Check
The Courage to Business Logic
Util & Helper (Hell)?
a.k.a. Manager
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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?
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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?
The Courage to Business Logic
Correct order?
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* 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 Pitfall!
The Courage to Business Logic
Voxxed
Days
The Courage to Business Logic
Problem Areas
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Problem Areas
Result of the Reality Check
‣ Anemic Domain Model
‣ non-meaningful API
‣ missing Null Value Handling
‣ inconsequent or missing Validation
‣ duplicated Code
‣ Util, Helper & Manager Hell
Voxxed
Days
Absence of
Code Stability!
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Problem Areas
Absence of Code Stability
‣ Team growth / reduction becomes a high Risk
‣ Where can i find the business logic?
‣ What the hell is this class doing exactly?
‣ Where do this stuff belongs to?
‣ Copy & Paste Design Pattern!
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Survival Guide
Voxxed
Days
offenkundiggut #WISSENTEILEN
Just as a Reminder
„We want a meaningful Domain Model
with an descriptive API, which can be
created and kept consistent during
its whole lifetime.“
The Courage to Business Logic
Survival Guide
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Survival Guide
Requirements
‣ meaningful Model
‣ descriptive API
‣ create consistently
‣ keep consistently
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Survival Guide
Rich Domain Model
‣ Business Logic
‣ Validation
‣ Conversion
‣ Normalization
‣ Consistency Checks
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Survival Guide
Refactoring Step by Step
‣ Step 1: Value Objects
‣ Step 2: Rich Entities
‣ Step 3: Builder Pattern
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 1: Value Objects
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 1: Value Objects
Voxxed
Days
„An object that contains
attributes but has 

no conceptual identity.
They should be treated
as immutable.“
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 1: Value Objects
Value Objects …
‣ #1: are Objects, not Primitives
‣ #2: are immutable
‣ #3: are doing business relevant conversion
‣ #4: are doing business relevant normalization
‣ #5: are doing business relevant validation
‣ #6: are „full blown“ Objects
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #1: Value Objects are Objects, not Primitives
*/
public class Customer {
private Date birthDate;
...
)
Step 1: Value Objects
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #1: Value Objects are Objects, not Primitives
*/
public class Customer {
private DateOfBirth birthDate;
...
)
„more than just a Date“
Step 1: Value Objects
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* Represents a date of birth
*/
public class DateOfBirth {
private Date dateOfBirth;
public boolean hasBirthDay() {
return ...;
}
public int getCurrentAge() {
return ...;
}
}
Step 1: Value Objects
The Courage to Business Logic
Voxxed
Days
„more than just a Date“
offenkundiggut #WISSENTEILEN
offenkundiggut #WISSENTEILEN
/**
* #2: Value Objects are immutable
*/
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());
}
...
}
Step 1: Value Objects
Immutable!
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #3: Value Objects are doing business relevant conversion
*/
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"
...;
}
...
}
Step 1: Value Objects
Conversion!
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #4: Value Objects are doing business relevant normalization
*/
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 ...;
}
...
}
Step 1: Value Objects
Normalization!
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #5: Value Objects are doing business relevant validation
*/
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 ...;
}
...
}
Step 1: Value Objects
Validation!
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #6: Value Objects are „full blown“ Objects
*/
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 ...;
}
}
Step 1: Value Objects
Full blown Object!
The Courage to Business Logic
Voxxed
Days
The Courage to Business Logic
Step 1: Value Objects
Value Objects Examples
‣ FirstName, LastName, DateOfBirth
‣ ZipCode, City, Country
‣ Email, PhoneNumber
‣ Note, Description
‣ Year, Month, …
‣ Money, …
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 1: Value Objects
Value Objects Benefits
‣ Business Code is part of the Domain
‣ Non / nearly non duplicated Code
‣ meaningful & consistent Code
‣ readable & maintainable Code
‣ No more Util, Helper, Manager & Friends
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 2: Rich Entities
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 2: Rich Entities
Voxxed
Days
„An object that is not
defined by its
attributes, but rather
by a thread of
continuity and its
identity.“
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 2: Rich Entities
„Golden Rules“ for rich Entities …
‣ #1: are consistent
‣ #2: Attributes are Value Objects, not Primitives
‣ #3: Setter only if needed by Business Logic
‣ #4: Methods are Business relevant Operations
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #1: Entities are consistent
*
*/
public class Customer {
private String lastName;
private Customer(String name) {
lastName = notNull(name);
};
...
)
Step 2: Rich Entities
The Courage to Business Logic
Voxxed
Days
commons.lang3.Validate
offenkundiggut #WISSENTEILEN
/**
* #2: Attributes are Value Objects, not Primitives
*/
public class Customer {
private String lastName;
…
)
Step 2: Rich Entities
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #2: Attributes are Value Objects, not Primitives
*/
public class Customer {
private LastName lastName;
…
)
Step 2: Rich Entities
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #3: Setter only if needed by Business Logic
*
*/
public class Customer {
private LastName lastName;
public Customer(LastName name) {
lastName = setLastname(name);
};
public void setLastName(LastName name) {
lastName = notNull(name);
};
...
)
Step 2: Rich Entities
The Courage to Business Logic
Voxxed
Days
BTW: Validation
offenkundiggut #WISSENTEILEN
/**
* #4: Methods are business relevant operations
*/
public class Customer {
private LastName lastName;
private boolean married;
private Person partner;
public void setLastName(LastName name) { … };
public void setMarried(boolean married) { … };
public void setPartner(Partner partner) { … };
…
)
Step 2: Rich Entities
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
/**
* #4: Methods are business relevant operations
*/
public class Customer {
private LastName lastName;
private FamilyStatus familyStatus;
private Person partner;
public void marry(Person partner, LastName aLastName) {
lastName = notNull(aLastName)
familyStatus = FamilyStatus.MARRIED;
partner = ...; //guarantee bidirectional consistency!
};
…
)
Step 2: Rich Entities
The Courage to Business Logic
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 3: Builder Pattern
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Step 3: Builder Pattern
Builder Pattern in a Nutshell
‣ Object Creation Design Pattern
‣ Answer to Constructor-Hell Anti-Pattern
‣ Step-by-Step approach
‣ Good candidate for a Fluent-API
Voxxed
Days
offenkundiggut #WISSENTEILEN
// 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
...;
}
Step 3: Builder Pattern
The Courage to Business Logic
Nice? Not really!
Voxxed
Days
offenkundiggut #WISSENTEILEN
// 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();
Step 3: Builder Pattern
The Courage to Business Logic
Nicer?
Voxxed
Days
offenkundiggut #WISSENTEILEN
offenkundiggut #WISSENTEILEN
// 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;
}
...
}
Step 3: Builder Pattern
The Courage to Business Logic
Kind of!
Voxxed
Days
// Builder Pattern - Extended Edition IN ACTION
// create AddressBuilder
Address address = Adress.newAddress()
// set values
.forStreetNumber(...).ofStreet(...)
.inCity(...).withZipCode(...)
.lyingInState(...).ofCountry(...)
// build VALID Address object
.build(...);
Step 3: Builder Pattern
The Courage to Business Logic
Nicest?
Voxxed
Days
offenkundiggut #WISSENTEILEN
// Builder Pattern - Extended Edition with Inner Class Builder
public class Address {
private Address() { /* empty constructor to prohibit use */ }
public static Builder newAddress() {
return new Address().new Builder();
}
private String street; ... // some more attributes
public class Builder {
public Builder ofStreet(String initialStreet) {
street = validateStreet(initialStreet);
return this;
}
... // some more methods to fill the Builder
public Address build() {
validate();
return Address.this;
}
}
}
Step 3: Builder Pattern
The Courage to Business Logic
Voxxed
Days
YES!
offenkundiggut #WISSENTEILEN
The Courage to Business Logic
Conclusion
Voxxed
Days
offenkundiggut #WISSENTEILEN
The Design is the Code,
the Code is the Design.
„Do i have to change my
Code if the Business
Logic changes?“
The Courage to Business Logic
Conclusion
Voxxed
Days
offenkundiggut #WISSENTEILEN
„Why the hell NOT? 

The Code is 

the Business Logic!“
The Courage to Business Logic
Conclusion
Voxxed
Days
offenkundiggut #WISSENTEILEN
@mobileLarson 

@_openKnowledge
Lars Röwekamp
CIO New Technologies
The Courage to Business Logic

#WISSENTEILEN
The Courage to Business Logic
Images …
‣ #1: iStock.com/Andrew Rich (36508576)
‣ #2: iStock.com/shironosov (46494512)
‣ #19: iStock.com/Peshkova (26981250)
‣ #22: iStock.com/Andrew Rich (35766696)
‣ #50: iStock.com/mcsilvey (1604024)
‣ #57: iStock.com/pinestock (44615094)
‣ #7: © vasakna - Fotolia.com
‣ #28, #41: pixarbay.com
Voxxed
Days
offenkundiggut #WISSENTEILEN

Weitere ähnliche Inhalte

Andere mochten auch

Mary Murtagh's Mission and Core Values
Mary Murtagh's Mission and Core ValuesMary Murtagh's Mission and Core Values
Mary Murtagh's Mission and Core ValuesMary Murtagh
 
Brave Communication Week 4
Brave Communication Week 4Brave Communication Week 4
Brave Communication Week 4rfochler
 
Affordable Housing Options in California and Hawaii
Affordable Housing Options in California and HawaiiAffordable Housing Options in California and Hawaii
Affordable Housing Options in California and HawaiiMary Murtagh
 
Courage Photo Essay
Courage Photo EssayCourage Photo Essay
Courage Photo Essaylovelylivi
 
Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)
Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)
Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)New City Church
 
The Art of Living Courageously Week 5: The Courageous Mindset
The Art of Living Courageously Week 5: The Courageous MindsetThe Art of Living Courageously Week 5: The Courageous Mindset
The Art of Living Courageously Week 5: The Courageous MindsetRoz Savage
 
M2013 s5 praying for boldness
M2013 s5 praying for boldnessM2013 s5 praying for boldness
M2013 s5 praying for boldnessJames Bradshaw
 
Leadership and management skills
Leadership and management skillsLeadership and management skills
Leadership and management skillsOH TEIK BIN
 
28 Great Book Quotes on Courage
28 Great Book Quotes on Courage28 Great Book Quotes on Courage
28 Great Book Quotes on CourageJoe Tye
 
Boldness and Humility
Boldness and HumilityBoldness and Humility
Boldness and Humilityrfochler
 
Part 4 - Persecution and Boldness
Part 4 - Persecution and BoldnessPart 4 - Persecution and Boldness
Part 4 - Persecution and BoldnessDerick Parfan
 
(Values) Honesty and Courage
(Values) Honesty and Courage(Values) Honesty and Courage
(Values) Honesty and Couragejustinesolano
 
Mandelas 8 Lessons Of Leadership
Mandelas 8 Lessons Of LeadershipMandelas 8 Lessons Of Leadership
Mandelas 8 Lessons Of LeadershipKaustuv Gupta
 

Andere mochten auch (17)

Mary Murtagh's Mission and Core Values
Mary Murtagh's Mission and Core ValuesMary Murtagh's Mission and Core Values
Mary Murtagh's Mission and Core Values
 
Brave Communication Week 4
Brave Communication Week 4Brave Communication Week 4
Brave Communication Week 4
 
Affordable Housing Options in California and Hawaii
Affordable Housing Options in California and HawaiiAffordable Housing Options in California and Hawaii
Affordable Housing Options in California and Hawaii
 
Courage in Leadership and Leadership in Courage
Courage in Leadership and Leadership in CourageCourage in Leadership and Leadership in Courage
Courage in Leadership and Leadership in Courage
 
Courage Photo Essay
Courage Photo EssayCourage Photo Essay
Courage Photo Essay
 
Courage
CourageCourage
Courage
 
Courage
CourageCourage
Courage
 
Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)
Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)
Sermon Slide Deck: "Shameless Boldness In Prayer" (Luke 11:1-8)
 
The Art of Living Courageously Week 5: The Courageous Mindset
The Art of Living Courageously Week 5: The Courageous MindsetThe Art of Living Courageously Week 5: The Courageous Mindset
The Art of Living Courageously Week 5: The Courageous Mindset
 
M2013 s5 praying for boldness
M2013 s5 praying for boldnessM2013 s5 praying for boldness
M2013 s5 praying for boldness
 
Leadership and management skills
Leadership and management skillsLeadership and management skills
Leadership and management skills
 
28 Great Book Quotes on Courage
28 Great Book Quotes on Courage28 Great Book Quotes on Courage
28 Great Book Quotes on Courage
 
Boldness and Humility
Boldness and HumilityBoldness and Humility
Boldness and Humility
 
Part 4 - Persecution and Boldness
Part 4 - Persecution and BoldnessPart 4 - Persecution and Boldness
Part 4 - Persecution and Boldness
 
Circle of courage
Circle of courageCircle of courage
Circle of courage
 
(Values) Honesty and Courage
(Values) Honesty and Courage(Values) Honesty and Courage
(Values) Honesty and Courage
 
Mandelas 8 Lessons Of Leadership
Mandelas 8 Lessons Of LeadershipMandelas 8 Lessons Of Leadership
Mandelas 8 Lessons Of Leadership
 

Ähnlich wie The courage to business logic – Business Driven Architecture

Agile Database Development with JSON
Agile Database Development with JSONAgile Database Development with JSON
Agile Database Development with JSONChris Saxon
 
Elixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.jsElixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.jsJeroen Visser
 
Application Frameworks an Experience Report
Application Frameworks an Experience ReportApplication Frameworks an Experience Report
Application Frameworks an Experience ReportESUG
 
SOLID in the Wild: Life when your software is actually soft
SOLID in the Wild: Life when your software is actually softSOLID in the Wild: Life when your software is actually soft
SOLID in the Wild: Life when your software is actually softVMware Tanzu
 
Big Retail Goes Reactive at Walmart
Big Retail Goes Reactive at WalmartBig Retail Goes Reactive at Walmart
Big Retail Goes Reactive at WalmartNurun
 
How to build a data warehouse - code.talks 2014
How to build a data warehouse - code.talks 2014How to build a data warehouse - code.talks 2014
How to build a data warehouse - code.talks 2014Martin Loetzsch
 
Reactive Applications in Enterprise Java
Reactive Applications in Enterprise JavaReactive Applications in Enterprise Java
Reactive Applications in Enterprise JavaOPEN KNOWLEDGE GmbH
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDDKonstantin Kudryashov
 
Building complex UI on Android
Building complex UI on AndroidBuilding complex UI on Android
Building complex UI on AndroidMaciej Witowski
 
Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!Nico Krijnen
 
Opticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer PlatformOpticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer PlatformOptimizely
 
Serverless Finland Meetup 16.11.2016: Messenger Bot Workshop
Serverless Finland Meetup 16.11.2016: Messenger Bot WorkshopServerless Finland Meetup 16.11.2016: Messenger Bot Workshop
Serverless Finland Meetup 16.11.2016: Messenger Bot WorkshopMikael Puittinen
 
Week 8
Week 8Week 8
Week 8A VD
 

Ähnlich wie The courage to business logic – Business Driven Architecture (20)

Agile Database Development with JSON
Agile Database Development with JSONAgile Database Development with JSON
Agile Database Development with JSON
 
Domain Driven Design 101
Domain Driven Design 101Domain Driven Design 101
Domain Driven Design 101
 
Elixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.jsElixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.js
 
Application Frameworks an Experience Report
Application Frameworks an Experience ReportApplication Frameworks an Experience Report
Application Frameworks an Experience Report
 
SOLID in the Wild: Life when your software is actually soft
SOLID in the Wild: Life when your software is actually softSOLID in the Wild: Life when your software is actually soft
SOLID in the Wild: Life when your software is actually soft
 
FactsERP software
FactsERP softwareFactsERP software
FactsERP software
 
Big Retail Goes Reactive at Walmart
Big Retail Goes Reactive at WalmartBig Retail Goes Reactive at Walmart
Big Retail Goes Reactive at Walmart
 
How to build a data warehouse - code.talks 2014
How to build a data warehouse - code.talks 2014How to build a data warehouse - code.talks 2014
How to build a data warehouse - code.talks 2014
 
Reactive Applications in Enterprise Java
Reactive Applications in Enterprise JavaReactive Applications in Enterprise Java
Reactive Applications in Enterprise Java
 
Facts erp best erp software dubai
Facts erp   best erp software dubaiFacts erp   best erp software dubai
Facts erp best erp software dubai
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
Vaadin 8 and 10
Vaadin 8 and 10Vaadin 8 and 10
Vaadin 8 and 10
 
Building complex UI on Android
Building complex UI on AndroidBuilding complex UI on Android
Building complex UI on Android
 
Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!Event Sourcing with Kotlin, who needs frameworks!
Event Sourcing with Kotlin, who needs frameworks!
 
Domain Event - The Hidden Gem of DDD
Domain Event - The Hidden Gem of DDDDomain Event - The Hidden Gem of DDD
Domain Event - The Hidden Gem of DDD
 
Opticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer PlatformOpticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer Platform
 
Serverless Finland Meetup 16.11.2016: Messenger Bot Workshop
Serverless Finland Meetup 16.11.2016: Messenger Bot WorkshopServerless Finland Meetup 16.11.2016: Messenger Bot Workshop
Serverless Finland Meetup 16.11.2016: Messenger Bot Workshop
 
Week 8
Week 8Week 8
Week 8
 
Viadeo - The Kasper way
Viadeo - The Kasper wayViadeo - The Kasper way
Viadeo - The Kasper way
 

Mehr von OPEN KNOWLEDGE GmbH

Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AIWarum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AIOPEN KNOWLEDGE GmbH
 
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...OPEN KNOWLEDGE GmbH
 
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die CloudFrom Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die CloudOPEN KNOWLEDGE GmbH
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data ImputationFEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data ImputationOPEN KNOWLEDGE GmbH
 
Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!OPEN KNOWLEDGE GmbH
 
From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud. From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud. OPEN KNOWLEDGE GmbH
 
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & CoReady for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & CoOPEN KNOWLEDGE GmbH
 
Shared Data in verteilten Architekturen
Shared Data in verteilten ArchitekturenShared Data in verteilten Architekturen
Shared Data in verteilten ArchitekturenOPEN KNOWLEDGE GmbH
 
Machine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.jsMachine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.jsOPEN KNOWLEDGE GmbH
 
It's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale NetzeIt's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale NetzeOPEN KNOWLEDGE GmbH
 
Shared Data in verteilten Systemen
Shared Data in verteilten SystemenShared Data in verteilten Systemen
Shared Data in verteilten SystemenOPEN KNOWLEDGE GmbH
 
Mehr Sicherheit durch Automatisierung
Mehr Sicherheit durch AutomatisierungMehr Sicherheit durch Automatisierung
Mehr Sicherheit durch AutomatisierungOPEN KNOWLEDGE GmbH
 
API-Design, Microarchitecture und Testing
API-Design, Microarchitecture und TestingAPI-Design, Microarchitecture und Testing
API-Design, Microarchitecture und TestingOPEN KNOWLEDGE GmbH
 
Supersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: QuarkusSupersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: QuarkusOPEN KNOWLEDGE GmbH
 
Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!OPEN KNOWLEDGE GmbH
 

Mehr von OPEN KNOWLEDGE GmbH (20)

Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AIWarum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
 
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
 
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die CloudFrom Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data ImputationFEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
 
Nie wieder Log-Files!
Nie wieder Log-Files!Nie wieder Log-Files!
Nie wieder Log-Files!
 
Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!
 
From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud. From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud.
 
API Expand Contract
API Expand ContractAPI Expand Contract
API Expand Contract
 
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & CoReady for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & Co
 
Shared Data in verteilten Architekturen
Shared Data in verteilten ArchitekturenShared Data in verteilten Architekturen
Shared Data in verteilten Architekturen
 
Machine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.jsMachine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.js
 
KI und Architektur
KI und ArchitekturKI und Architektur
KI und Architektur
 
It's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale NetzeIt's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale Netze
 
Shared Data in verteilten Systemen
Shared Data in verteilten SystemenShared Data in verteilten Systemen
Shared Data in verteilten Systemen
 
Business-Mehrwert durch KI
Business-Mehrwert durch KIBusiness-Mehrwert durch KI
Business-Mehrwert durch KI
 
Mehr Sicherheit durch Automatisierung
Mehr Sicherheit durch AutomatisierungMehr Sicherheit durch Automatisierung
Mehr Sicherheit durch Automatisierung
 
API-Design, Microarchitecture und Testing
API-Design, Microarchitecture und TestingAPI-Design, Microarchitecture und Testing
API-Design, Microarchitecture und Testing
 
Supersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: QuarkusSupersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: Quarkus
 
Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!
 

Kürzlich hochgeladen

Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...software pro Development
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 

Kürzlich hochgeladen (20)

Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 

The courage to business logic – Business Driven Architecture

  • 1. @mobileLarson 
 @_openKnowledge Lars Röwekamp CIO New Technologies The Courage to Business Logic
 #WISSENTEILEN
  • 2. Business vs. Technology The Courage to Business Logic Voxxed Days „May I submit my billing info 
 to your merchant account 
 via your payment gateway?“ offenkundiggut #WISSENTEILEN
  • 3. Business vs. Technology The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 4. The Courage to Business Logic End User Domain Expert Technical Expert Ubiquitous Language „Common language as the basis for a consistent domain model.“ Business vs. Technology Voxxed Days offenkundiggut #WISSENTEILEN
  • 5. „Produce Software 
 that makes perfectly 
 sense to business, 
 not only to coder“ The Courage to Business Logic End User Domain Expert Technical Expert Rich Domain Model Business vs. Technology Voxxed Days offenkundiggut #WISSENTEILEN
  • 6. „Produce Software 
 that is always 
 in a correct state, 
 not only partially“ The Courage to Business Logic Domain Expert Technical Expert Rich Domain Model Business vs. Technology Access Layer Business Layer DB Layer Voxxed Days offenkundiggut #WISSENTEILEN
  • 7. The Courage to Business Logic Reality Check The déjà-vu Experiment Voxxed Days offenkundiggut #WISSENTEILEN
  • 8. offenkundiggut #WISSENTEILEN /** * 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 lastName; private Date birthDate; private Address address; public void setFirstName(String aFirstName) { ... } public String getFirstName() { return firstName; } public void setLastName(String aLastName) { ... } public String getLastName() { return lastName; } public void setBirthDate(Date birthDate) { ... } public Date getBirthDate() { return birthDate; } public void setAddress(Address address) { ... } public Address getAddress() { return address; } } Reality Check „Business“ Logic? The Courage to Business Logic Voxxed Days
  • 9. offenkundiggut #WISSENTEILEN /** * 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 lastName, String zipCode, String city) { ... } public Customer(String firstName, String lastName, String zipCode, String city, String street) { ... } ... } Reality Check Parameter (Hell)? The Courage to Business Logic Constructor (Hell)? Voxxed Days
  • 10. offenkundiggut #WISSENTEILEN Reality Check The Courage to Business Logic /** * 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, String, String, String) { ... } public Customer(String, String, String, String, String) { ... } ... } „no-Sources“ View Voxxed Days
  • 11. offenkundiggut #WISSENTEILEN /** * 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 lastName, String zipCode, String city) { Validate.isTrue(StringUtils.isNotEmpty(firstName)); Validate.isTrue(StringUtils.isNotEmpty(sureName)); ... } public void setFirstName(String firstName) { this.firstName = firstName; } ... } Reality Check The Courage to Business Logic Validation? Voxxed Days
  • 12. offenkundiggut #WISSENTEILEN /** * 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 ZIP_CODE_PATTERN = ...; public Customer(String firstName, String sureName, String zipCode, String city) { setFirstName(firstName); setZipCode(zipCode); ... } public void setZipCode(String zipCode) { Validate.isTrue(Pattern.matches(ZIP_CODE_PATTERN, zipCode)); } ... } Reality Check The Courage to Business Logic Right place? Voxxed Days
  • 13. offenkundiggut #WISSENTEILEN /** * 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 Check The Courage to Business Logic Conversion? Voxxed Days
  • 14. offenkundiggut #WISSENTEILEN /** * 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 Check The Courage to Business Logic Evaluation? Voxxed Days
  • 15. offenkundiggut #WISSENTEILEN /** * 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 Check The Courage to Business Logic Util & Helper (Hell)? a.k.a. Manager Voxxed Days
  • 16. offenkundiggut #WISSENTEILEN /** * 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? The Courage to Business Logic Voxxed Days
  • 17. offenkundiggut #WISSENTEILEN /** * 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? The Courage to Business Logic Correct order? Voxxed Days
  • 18. offenkundiggut #WISSENTEILEN /** * 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 Pitfall! The Courage to Business Logic Voxxed Days
  • 19. The Courage to Business Logic Problem Areas Voxxed Days offenkundiggut #WISSENTEILEN
  • 20. The Courage to Business Logic Problem Areas Result of the Reality Check ‣ Anemic Domain Model ‣ non-meaningful API ‣ missing Null Value Handling ‣ inconsequent or missing Validation ‣ duplicated Code ‣ Util, Helper & Manager Hell Voxxed Days Absence of Code Stability! offenkundiggut #WISSENTEILEN
  • 21. The Courage to Business Logic Problem Areas Absence of Code Stability ‣ Team growth / reduction becomes a high Risk ‣ Where can i find the business logic? ‣ What the hell is this class doing exactly? ‣ Where do this stuff belongs to? ‣ Copy & Paste Design Pattern! Voxxed Days offenkundiggut #WISSENTEILEN
  • 22. The Courage to Business Logic Survival Guide Voxxed Days offenkundiggut #WISSENTEILEN
  • 23. Just as a Reminder „We want a meaningful Domain Model with an descriptive API, which can be created and kept consistent during its whole lifetime.“ The Courage to Business Logic Survival Guide Voxxed Days offenkundiggut #WISSENTEILEN
  • 24. The Courage to Business Logic Survival Guide Requirements ‣ meaningful Model ‣ descriptive API ‣ create consistently ‣ keep consistently Voxxed Days offenkundiggut #WISSENTEILEN
  • 25. The Courage to Business Logic Survival Guide Rich Domain Model ‣ Business Logic ‣ Validation ‣ Conversion ‣ Normalization ‣ Consistency Checks Voxxed Days offenkundiggut #WISSENTEILEN
  • 26. The Courage to Business Logic Survival Guide Refactoring Step by Step ‣ Step 1: Value Objects ‣ Step 2: Rich Entities ‣ Step 3: Builder Pattern Voxxed Days offenkundiggut #WISSENTEILEN
  • 27. The Courage to Business Logic Step 1: Value Objects Voxxed Days offenkundiggut #WISSENTEILEN
  • 28. The Courage to Business Logic Step 1: Value Objects Voxxed Days „An object that contains attributes but has 
 no conceptual identity. They should be treated as immutable.“ offenkundiggut #WISSENTEILEN
  • 29. The Courage to Business Logic Step 1: Value Objects Value Objects … ‣ #1: are Objects, not Primitives ‣ #2: are immutable ‣ #3: are doing business relevant conversion ‣ #4: are doing business relevant normalization ‣ #5: are doing business relevant validation ‣ #6: are „full blown“ Objects Voxxed Days offenkundiggut #WISSENTEILEN
  • 30. /** * #1: Value Objects are Objects, not Primitives */ public class Customer { private Date birthDate; ... ) Step 1: Value Objects The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 31. /** * #1: Value Objects are Objects, not Primitives */ public class Customer { private DateOfBirth birthDate; ... ) „more than just a Date“ Step 1: Value Objects The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 32. /** * Represents a date of birth */ public class DateOfBirth { private Date dateOfBirth; public boolean hasBirthDay() { return ...; } public int getCurrentAge() { return ...; } } Step 1: Value Objects The Courage to Business Logic Voxxed Days „more than just a Date“ offenkundiggut #WISSENTEILEN
  • 33. offenkundiggut #WISSENTEILEN /** * #2: Value Objects are immutable */ 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()); } ... } Step 1: Value Objects Immutable! The Courage to Business Logic Voxxed Days
  • 34. offenkundiggut #WISSENTEILEN /** * #3: Value Objects are doing business relevant conversion */ 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" ...; } ... } Step 1: Value Objects Conversion! The Courage to Business Logic Voxxed Days
  • 35. offenkundiggut #WISSENTEILEN /** * #4: Value Objects are doing business relevant normalization */ 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 ...; } ... } Step 1: Value Objects Normalization! The Courage to Business Logic Voxxed Days
  • 36. offenkundiggut #WISSENTEILEN /** * #5: Value Objects are doing business relevant validation */ 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 ...; } ... } Step 1: Value Objects Validation! The Courage to Business Logic Voxxed Days
  • 37. offenkundiggut #WISSENTEILEN /** * #6: Value Objects are „full blown“ Objects */ 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 ...; } } Step 1: Value Objects Full blown Object! The Courage to Business Logic Voxxed Days
  • 38. The Courage to Business Logic Step 1: Value Objects Value Objects Examples ‣ FirstName, LastName, DateOfBirth ‣ ZipCode, City, Country ‣ Email, PhoneNumber ‣ Note, Description ‣ Year, Month, … ‣ Money, … Voxxed Days offenkundiggut #WISSENTEILEN
  • 39. The Courage to Business Logic Step 1: Value Objects Value Objects Benefits ‣ Business Code is part of the Domain ‣ Non / nearly non duplicated Code ‣ meaningful & consistent Code ‣ readable & maintainable Code ‣ No more Util, Helper, Manager & Friends Voxxed Days offenkundiggut #WISSENTEILEN
  • 40. The Courage to Business Logic Step 2: Rich Entities Voxxed Days offenkundiggut #WISSENTEILEN
  • 41. The Courage to Business Logic Step 2: Rich Entities Voxxed Days „An object that is not defined by its attributes, but rather by a thread of continuity and its identity.“ offenkundiggut #WISSENTEILEN
  • 42. The Courage to Business Logic Step 2: Rich Entities „Golden Rules“ for rich Entities … ‣ #1: are consistent ‣ #2: Attributes are Value Objects, not Primitives ‣ #3: Setter only if needed by Business Logic ‣ #4: Methods are Business relevant Operations Voxxed Days offenkundiggut #WISSENTEILEN
  • 43. /** * #1: Entities are consistent * */ public class Customer { private String lastName; private Customer(String name) { lastName = notNull(name); }; ... ) Step 2: Rich Entities The Courage to Business Logic Voxxed Days commons.lang3.Validate offenkundiggut #WISSENTEILEN
  • 44. /** * #2: Attributes are Value Objects, not Primitives */ public class Customer { private String lastName; … ) Step 2: Rich Entities The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 45. /** * #2: Attributes are Value Objects, not Primitives */ public class Customer { private LastName lastName; … ) Step 2: Rich Entities The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 46. /** * #3: Setter only if needed by Business Logic * */ public class Customer { private LastName lastName; public Customer(LastName name) { lastName = setLastname(name); }; public void setLastName(LastName name) { lastName = notNull(name); }; ... ) Step 2: Rich Entities The Courage to Business Logic Voxxed Days BTW: Validation offenkundiggut #WISSENTEILEN
  • 47. /** * #4: Methods are business relevant operations */ public class Customer { private LastName lastName; private boolean married; private Person partner; public void setLastName(LastName name) { … }; public void setMarried(boolean married) { … }; public void setPartner(Partner partner) { … }; … ) Step 2: Rich Entities The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 48. /** * #4: Methods are business relevant operations */ public class Customer { private LastName lastName; private FamilyStatus familyStatus; private Person partner; public void marry(Person partner, LastName aLastName) { lastName = notNull(aLastName) familyStatus = FamilyStatus.MARRIED; partner = ...; //guarantee bidirectional consistency! }; … ) Step 2: Rich Entities The Courage to Business Logic Voxxed Days offenkundiggut #WISSENTEILEN
  • 49. The Courage to Business Logic Step 3: Builder Pattern Voxxed Days offenkundiggut #WISSENTEILEN
  • 50. The Courage to Business Logic Step 3: Builder Pattern Builder Pattern in a Nutshell ‣ Object Creation Design Pattern ‣ Answer to Constructor-Hell Anti-Pattern ‣ Step-by-Step approach ‣ Good candidate for a Fluent-API Voxxed Days offenkundiggut #WISSENTEILEN
  • 51. // 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 ...; } Step 3: Builder Pattern The Courage to Business Logic Nice? Not really! Voxxed Days offenkundiggut #WISSENTEILEN
  • 52. // 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(); Step 3: Builder Pattern The Courage to Business Logic Nicer? Voxxed Days offenkundiggut #WISSENTEILEN
  • 53. offenkundiggut #WISSENTEILEN // 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; } ... } Step 3: Builder Pattern The Courage to Business Logic Kind of! Voxxed Days
  • 54. // Builder Pattern - Extended Edition IN ACTION // create AddressBuilder Address address = Adress.newAddress() // set values .forStreetNumber(...).ofStreet(...) .inCity(...).withZipCode(...) .lyingInState(...).ofCountry(...) // build VALID Address object .build(...); Step 3: Builder Pattern The Courage to Business Logic Nicest? Voxxed Days offenkundiggut #WISSENTEILEN
  • 55. // Builder Pattern - Extended Edition with Inner Class Builder public class Address { private Address() { /* empty constructor to prohibit use */ } public static Builder newAddress() { return new Address().new Builder(); } private String street; ... // some more attributes public class Builder { public Builder ofStreet(String initialStreet) { street = validateStreet(initialStreet); return this; } ... // some more methods to fill the Builder public Address build() { validate(); return Address.this; } } } Step 3: Builder Pattern The Courage to Business Logic Voxxed Days YES! offenkundiggut #WISSENTEILEN
  • 56. The Courage to Business Logic Conclusion Voxxed Days offenkundiggut #WISSENTEILEN The Design is the Code, the Code is the Design.
  • 57. „Do i have to change my Code if the Business Logic changes?“ The Courage to Business Logic Conclusion Voxxed Days offenkundiggut #WISSENTEILEN
  • 58. „Why the hell NOT? 
 The Code is 
 the Business Logic!“ The Courage to Business Logic Conclusion Voxxed Days offenkundiggut #WISSENTEILEN
  • 59. @mobileLarson 
 @_openKnowledge Lars Röwekamp CIO New Technologies The Courage to Business Logic
 #WISSENTEILEN
  • 60. The Courage to Business Logic Images … ‣ #1: iStock.com/Andrew Rich (36508576) ‣ #2: iStock.com/shironosov (46494512) ‣ #19: iStock.com/Peshkova (26981250) ‣ #22: iStock.com/Andrew Rich (35766696) ‣ #50: iStock.com/mcsilvey (1604024) ‣ #57: iStock.com/pinestock (44615094) ‣ #7: © vasakna - Fotolia.com ‣ #28, #41: pixarbay.com Voxxed Days offenkundiggut #WISSENTEILEN