Slide 1

Slide 1 text

" Robert Bräutigam MATHEMA So ware GmbH. OBJECT-ORIENTED DOMAIN DRIVEN DESIGN

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

GOAL TO INTRODUCE A NEW** DESIGN PARADIGM WHICH INCREASES MAINTAINABILITY* OF SOFTWARE.

Slide 4

Slide 4 text

OO AND DDD? ISN'T THAT REDUNTANT?

Slide 5

Slide 5 text

WHAT WE LEARN... public interface Animal { void speak(); } public final class Cat implements Animal { @Override public void speak() { System.out.println("Meow..."); } } public final class Dog implements Animal { @Override public void speak() { System.out.println("Woof..."); } }

Slide 6

Slide 6 text

"ENTERPRISE" CODE... public interface Animal { String getSpeech(); } public final class Cat implements Animal { private final String speech; ... @Override public String getSpeech() { return speech; } } public final class SpeechService { public void speak(Animal animal) { System.out.println(animal.getSpeech()); } }

Slide 7

Slide 7 text

WAIT A SECOND...

Slide 8

Slide 8 text

WHAT IS ENCAPSULATION THEN? It means having public and private parts. It means having secrets! Having secrets means to have an effective abstraction Effective abstraction means to solve a problem we don't have to think about ever again.

Slide 9

Slide 9 text

WHERE IS MY ENCAPSULATION? public interface Animal { String getSpeech(); } public final class Cat implements Animal { private final String speech; ... @Override public String getSpeech() { return speech; } } public final class SpeechService { public void speak(Animal animal) { System.out.println(animal.getSpeech()); } }

Slide 10

Slide 10 text

THESE THINGS TOO? Cohesion Coupling Tell, don't ask Law of Demeter etc... GO HOME AND RETHINK YOUR LIFE

Slide 11

Slide 11 text

OK, SO NOW WHAT? Objects must have hidden state Objects should do stuff, instead of giving out data Objects' instance variables should not be given out ⇒ SOUNDS LIKE WE SHOULD AVOID GETTERS

Slide 12

Slide 12 text

HOW DO WE DO DDD WITHOUT GETTERS

Slide 13

Slide 13 text

BUILDING BLOCKS OF DDD

Slide 14

Slide 14 text

VALUE OBJECTS Things that do not have an identity. Objects representing the same value are interchangeable.

Slide 15

Slide 15 text

COMMONLY IMPLEMENTED AS public final class Amount { private final BigDecimal value; private final Currency currency; public Amount(BigDecimal value, Currency currency) { this.value = value; this.currency = currency; } public BigDecimal getValue() { return value; } public Currency getCurrency() { return value; } ...equals(), hashCode(), toString()... }

Slide 16

Slide 16 text

THAT'S NOT COOL! There is nothing hidden. Therefore there is no problem solved here. This thing has no reason to exist! HOW CAN WE FIX THIS?

Slide 17

Slide 17 text

The business people talk a lot about "Amounts", so let's assume it's something we need to have. What business problem could the "Amount" solve?

Slide 18

Slide 18 text

OO VALUE OBJECT public final class Amount { private final BigDecimal value; private final Currency currency; public Amount(BigDecimal value, Currency currency) { this.value = value; this.currency = currency; } public Amount add(Amount other) { ... } public boolean largerThan(Amount other) { ... } ... }

Slide 19

Slide 19 text

ENTITY OBJECTS Things that have an identity. Objects are not interchangeable. Objects may represent the same conceptual thing even if some attributes differ.

Slide 20

Slide 20 text

COMMONLY SEEN AS: OH NO, NOT AGAIN! public final class Customer { private final CustomerId customerId; private Name name; ... public Customer(CustomerId customerId, Name name, ...) { this.customerId = customerId; this.name = name; ... } ...getters, some setters... }

Slide 21

Slide 21 text

HOW IT SHOULD LOOK: public final class Customer { ...data doesn't matter... public void renameTo(Name newName) { ... } public void freezeCreditCards() { ... } public void unfreezeCreditCards() { ... } public CreditStatement createCreditStatement() { ... } ... }

Slide 22

Slide 22 text

SERVICES "Sometimes, it just isn't a thing." -- Eric Evans Everything is an object. -- OO "...any decomposition, however complicated the domain, will result in the identification of a relatively few kinds of objects and only objects. There will be nothing "le over" that is not an object." -- David West

Slide 23

Slide 23 text

"FIXING" SERVICES "There are important domain operations that can't find a natural home in an ENTITY or VALUE OBJECT." -- Eric Evans Aha! It's not OO's fault, the building blocks are incomplete!

Slide 24

Slide 24 text

PASSWORDSERVICE (Vaughn Vernon) WHY? public class PasswordService { ...no hidden state... public String generateStrongPassword(); public boolean isStrong(String password); public boolean isWeak(String password); ... }

Slide 25

Slide 25 text

PASSWORD It's actually a Value Object. public final class Password { private final String password; public Password(String password) { this.password = password; } public boolean isStrong() { ... } public boolean isWeak() { ... } public static Password generateStrongPassword() { ... } }

Slide 26

Slide 26 text

GroupMemberService.isMemberGroup() public boolean isMemberGroup(Group aGroup, GroupMember aMemberGroup boolean isMember = false; Iterator iter = aGroup.groupMembers().iterator(); while (!isMember && iter.hasNext()) { GroupMember member = iter.next(); if (member.isGroup()) { if (aMemberGroup.equals(member)) { isMember = true; } else { Group group = this.groupRepository().groupNamed(member.tenantId(), if (group != null) { isMember = this.isMemberGroup(group, aMemberGroup); } } } } return isMember; }

Slide 27

Slide 27 text

Why not Group.contains()? public final class Group implements GroupMember { private final Set members; ... @Override public boolean contains(GroupMember potentialMember) { if (equals(potentialMember)) { return true; } return members.stream() .filter(member → member.contains(potentialMember)) .findFirst() .isPresent(); } } public final class User implements GroupMember { ... @Override public boolean contains(GroupMember potentialMember) { return equals(potentialMember); } }

Slide 28

Slide 28 text

REPOSITORIES A means to get an initial reference to an object. "Provide methods to add and remove objects... [and] methods that select objects..." -- Eric Evans In other words a CRUD service.

Slide 29

Slide 29 text

PROBLEMS WITH REPOSITORIES Reinforces data-based thinking Not part of the Domain! Repositories are technical. O en implemented by violating encapsulation...

Slide 30

Slide 30 text

REPOSITORY VS. ENCAPSULATION NOT OK! // Simplified from Vaughn Vernon's example public class LevelDBTeamRepository { ... public void save(Team team) { String id = team.getTeamId().getId(); // LoD violation String name = team.getName(); // Privacy violation ...persist team to id + name... } }

Slide 31

Slide 31 text

PERSISTENCE OPTION #1 public final class SqlCustomer implements Customer { private final Connection connection; private final String customerId; public SqlCustomer(String customerId, Connection connection) { this.customerId = customerId; this.connection = connection; } @Override public void freezeCreditCards() { connection.execute("update card set valid = 0 "+ "where customerId = ?", customerId); } }

Slide 32

Slide 32 text

PERSISTENCE OPTION #2 public final class Customer { ...private parts... public Json toJson() { ... } public static Customer fromJson(Json json) { ... } }

Slide 33

Slide 33 text

AGGREGATE ROOT Entities that exclusively control a set of internal entities and value objects. Outside objects are not allowed to hold references to internals, and the aggregate root entity controls access, preserves invariants. Well, all objects must do this anyway...

Slide 34

Slide 34 text

LAYERED ARCHITECTURE

Slide 35

Slide 35 text

PROBLEMS WITH LAYERS The "Domain" is only 1/4 of the Application Layers usually leak data upwards and create coupling (DTOs) UI usually tightly coupled to Domain UI (external interfaces) is usually second rate citizen

Slide 36

Slide 36 text

UI OF OBJECTS import org.apache.wicket.Component; public final class AccountNumber { private final String accountNumber; ... public Component display(String componentId) { return new Label(componentId, accountNumber); } }

Slide 37

Slide 37 text

UI OF OBJECTS import org.apache.wicket.Component; public final class AccountNumber { private final String accountNumber; ... public Component display(String componentId) { return new Label(componentId, accountNumber); } public FormComponent displayEditable(String compon return new TextField<>(componentId, ...); } }

Slide 38

Slide 38 text

SUMMARY

Slide 39

Slide 39 text

BUILDING BLOCKS OF OO DDD

Slide 40

Slide 40 text

OO DDD Ok, maybe we should not concentrate on the orignal building blocks! But, things that DDD adds to OO: Learn and think about the domain. (As opposed to technical stuff including building blocks) Exercise and speak the design Ubiquitous language Bounded Context

Slide 41

Slide 41 text

THANKS

Slide 42

Slide 42 text

QUESTIONS? [email protected] https://javadevguy.wordpress.com/ @robertbrautigam