Slide 1

Slide 1 text

WRITING CLEANER CODE WITH DOMAIN-DRIVEN DESIGN 1

Slide 2

Slide 2 text

What is DDD? Ubiquitous Language Supple Design Bounded Context What’s next? 2

Slide 3

Slide 3 text

What is DDD? 3

Slide 4

Slide 4 text

What is DDD? 4

Slide 5

Slide 5 text

What is DDD? 5

Slide 6

Slide 6 text

What is DDD? 6 • Domain-Driven Design & Bounded Context

Slide 7

Slide 7 text

What is DDD? 7

Slide 8

Slide 8 text

What is DDD? 8 Most of the core concepts are still relevant

Slide 9

Slide 9 text

What is DDD? 9

Slide 10

Slide 10 text

What is DDD? 10

Slide 11

Slide 11 text

What is DDD? 11 Aneamic domain model Data vs behaviour Tell don’t Ask How to split a bigger system

Slide 12

Slide 12 text

What is DDD? 12 You might want to dive into Domain- Driven Design

Slide 13

Slide 13 text

What is DDD? 13

Slide 14

Slide 14 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini Approach to software development • Focus on learning What is DDD? 14

Slide 15

Slide 15 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini Approach to software development • Focus on learning • Language as a first class citizen What is DDD? 15

Slide 16

Slide 16 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini Approach to software development • Focus on learning • Language as a first class citizen • Multiple models is the key for not evolving into a big ball of mud. What is DDD? 16

Slide 17

Slide 17 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini Approach to software development • Focus on learning • Language as a first class citizen • Multiple models is the key for not evolving into a big ball of mud. • Good coding practices are expected. What is DDD? 17

Slide 18

Slide 18 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini Approach to software development • Focus on learning • Language as a first class citizen • Multiple models is the key for not evolving into a big ball of mud. • Good coding practices are expected. • Know your core domain What is DDD? 18

Slide 19

Slide 19 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini • Focus on learning • Language as a first class citizen • Multiple models is the key for not evolving into a big ball of mud. • Good coding practices are expected. • Know your core domain What is DDD? 19

Slide 20

Slide 20 text

BLOG: Domain-Driven Design in 2020, by Alberto Brandolini • Focus on learning • Language as a first class citizen • Multiple models is the key for not evolving into a big ball of mud. • Good coding practices are expected. • Know your core domain What is DDD? 20

Slide 21

Slide 21 text

21

Slide 22

Slide 22 text

Who am I Paul van der Slot • Freelance Software Engineer • Fan of a lot of software practices and techniques like: DDD, Collaborative Design, Clean Code, Hexagonal Architecture, Refactoring, Agile, XP, TDD, Pair Programming, and way more 22

Slide 23

Slide 23 text

What is DDD? Ubiquitous Language Supple Design Bounded Context What’s next? 23

Slide 24

Slide 24 text

Introduction Ubiquitous Language Ubiquitous Language 24 Developer and Domain Expert talking Shipment Cargo

Slide 25

Slide 25 text

25 Ubiquitous Language Scrum Team Code Test Scenarios User Stories Domain experts specific for a domain Ubiquitous Language

Slide 26

Slide 26 text

26 Ubiquitous Language Scrum Team Code Test Scenarios User Stories Domain experts specific for a domain Ubiquitous Language

Slide 27

Slide 27 text

27 Code Domain model Ubiquitous Language customer payment invoice product customer payment invoice product

Slide 28

Slide 28 text

28 “Tackling complexity in the heart of software”

Slide 29

Slide 29 text

29 Code Domain model Ubiquitous Language customer payment invoice product customer payment invoice product DB Caching REST Monitoring

Slide 30

Slide 30 text

30 Code Domain model Ubiquitous Language customer payment invoice product customer payment invoice product DB Caching REST Monitoring Domain logic matching with the business problem Separate technical details from the domain logic As little as possible accidental complexity in domain

Slide 31

Slide 31 text

Hexagonal Architecture 31 Alistair Cockburn

Slide 32

Slide 32 text

Hexagonal Architecture 32 Your business logic should evolve because of the business evolution and nothing else.

Slide 33

Slide 33 text

public class CardService { private CardDetailsRestClient restclient; private CardsRepository cardRepository; void activateCards(List cardIds){ List cardDetails = restClient.getExtraCardInformation(cardIds); List dbCards = cardRepository.getCards(cardIds); activateCards(dbCards, cardDetails); } } 33

Slide 34

Slide 34 text

public class CardService { private CardDetailsRestClient restclient; private CardsRepository cardRepository; void activateCards(List cardIds){ List cardDetails = restClient.getExtraCardInformation(cardIds); List dbCards = cardRepository.getCards(cardIds); activateCards(dbCards, cardDetails); } private List activateCards(List dbCards, List cardDetails){ // do validation / transformation / null checks of external data // business logic updatedDbCards.forEach(cardRepository::save); } } 34

Slide 35

Slide 35 text

public class CardService { private CardsRepository cardRepository; void activateCards(List cardIds){ List cards = cardRepository.findAll(cardIds); activateCards(cards); } private void activateCards(List cards){ // business logic updatedCards.forEach(cardRepository::save); } } 35 public class CardService { private CardDetailsRestClient restclient; private CardsRepository cardRepository; void activateCards(List cardIds){ List cardDetails = restClient.getExtraCardInformation(cardIds); List dbCards = cardRepository.getCards(cardIds); activateCards(dbCards, cardDetails); } private List activateCards(List dbCards, List cardDetails){ // do validation / transformation / null checks of external data // business logic updatedDbCards.forEach(cardRepository::save); } }

Slide 36

Slide 36 text

public class CardService { private CardsRepository cardRepository; void activateCards(List cardIds){ List cards = cardRepository.findAll(cardIds); activateCards(cards); } private void activateCards(List cards){ // business logic updatedCards.forEach(cardRepository::save); } } interface CardsRepository { // port List findAll(List cardId); void save(Card card); } 36 public class CardService { private CardDetailsRestClient restclient; private CardsRepository cardRepository; void activateCards(List cardIds){ List cardDetails = restClient.getExtraCardInformation(cardIds); List dbCards = cardRepository.getCards(cardIds); activateCards(dbCards, cardDetails); } private List activateCards(List dbCards, List cardDetails){ // do validation / transformation / null checks of external data // business logic updatedDbCards.forEach(cardRepository::save); } }

Slide 37

Slide 37 text

public class CardService { private CardsRepository cardRepository; void activateCards(List cardIds){ List cards = cardRepository.findAll(cardIds); activateCards(cards); } private void activateCards(List cards){ // business logic updatedCards.forEach(cardRepository::save); } } interface CardsRepository { // port List findAll(List cardId); void save(Card card); } // Outside business logic, in an adapter class MongoCardRepository implements CardsRepository { // do validation / transformation / null checks } 37 public class CardService { private CardDetailsRestClient restclient; private CardsRepository cardRepository; void activateCards(List cardIds){ List cardDetails = restClient.getExtraCardInformation(cardIds); List dbCards = cardRepository.getCards(cardIds); activateCards(dbCards, cardDetails); } private List activateCards(List dbCards, List cardDetails){ // do validation / transformation / null checks of external data // business logic updatedDbCards.forEach(cardRepository::save); } }

Slide 38

Slide 38 text

38

Slide 39

Slide 39 text

39 “Make the Implicit Explicit”

Slide 40

Slide 40 text

40

Slide 41

Slide 41 text

Value Object 41 A Value Object is an immutable type that is distinguishable only by the state of its properties. Examples: Height, Money, AccountNumber, Color

Slide 42

Slide 42 text

Value Object 42 A Value Object is an immutable type that is distinguishable only by the state of its properties. Examples: Height, Money, AccountNumber, Color Using new Types (Value Objects) to make your code more explicit

Slide 43

Slide 43 text

43 void checkIn(int roomNumber){ validatePositive(roomNumber); int floorNumber = determineFloor(roomNumber); // do check in logic } int determineFloor(int roomNumber){ validatePositive(roomNumber); // do logic } Dan Bergh Johnsson - The Power of Value

Slide 44

Slide 44 text

44 void checkIn(RoomNumber roomNumber){ Floor floor = roomNumber.getFloor(); // do check in logic }

Slide 45

Slide 45 text

45 void checkIn(RoomNumber roomNumber){ Floor floor = roomNumber.getFloor(); // do check in logic } • Validation inside the Value Object • Limit operations to useful ones. RoomNumber is not an int! No + - * / • Place to put logic relevant to a Domain Concept, like getFloor()

Slide 46

Slide 46 text

Value object Center of gravity for (complex) business logic Immutable, easy to test 46

Slide 47

Slide 47 text

Value object vs Util method 47 Email Validation duplicated around the codebase boolean matchesPattern(String inputValue){ Pattern p = Pattern .compile(" ^[a-zA-Z0-9_!#$%&’*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$ "); Matcher m = p.matcher(inputValue); return m.matches(); }

Slide 48

Slide 48 text

Value object vs Util method 48 • Call the Util when you need to validate • You need to know the UTIL exists (not forcing) • You don’t know if the email is validated yet, later on in the code EmailUtil.matchesPattern(emailAddress); Option 1: Put it in a Utillity class

Slide 49

Slide 49 text

Value object vs Util method 49 • Everywhere, you use the validated Email • Email type as a parameter later on (type safe) • Explicit domain meaning Email email = new Email(emailAddress); Option 2: Create a Value Object

Slide 50

Slide 50 text

From Stringly typed / primitive obsession to domain primitives Talk with your team and introduce a ubiquitous language 50

Slide 51

Slide 51 text

From Stringly typed / primitive obsession to domain primitives learning concepts -> introduce in code 51

Slide 52

Slide 52 text

From Stringly typed / primitive obsession to domain primitives learning concepts -> introduce in code current understanding -> reflected in code 52

Slide 53

Slide 53 text

From Stringly typed / primitive obsession to domain primitives learning concepts -> introduce in code current understanding -> reflected in code change in code -> verify with business and change shared model 53

Slide 54

Slide 54 text

From Stringly typed / primitive obsession to domain primitives learning concepts -> introduce in code current understanding -> reflected in code change in code -> verify with business and change shared model iterative process 54

Slide 55

Slide 55 text

55

Slide 56

Slide 56 text

56 “Tell Don’t Ask”

Slide 57

Slide 57 text

TELL DON’T ASK 57 Tell an object what to do instead of asking for internal data to do it yourself This invites you to add the behavior in the object the data belongs to!

Slide 58

Slide 58 text

TELL DON’T ASK 58 public boolean canBeActivated(Card card) { Account account = card.getAccount(); if(account.isBlocked()){ return false; } Customer owner = card.getOwner(); if(owner != null && isTrustworthy(owner)){ return false; } return true; }

Slide 59

Slide 59 text

TELL DON’T ASK 59 public boolean canBeActivated(Card card) { return card.canBeActivated(); }

Slide 60

Slide 60 text

60 “Getters and Setters are evil” Tell don’t Ask Allen Holub

Slide 61

Slide 61 text

GETTERS AND SETTERS ARE EVIL 61 patient.setShotType(ShotTypes.TYPE_FLU); patient.setDose(dose); patient.setNurse(nurse); Vaccine vaccine = vaccines. standardAdultFluDose(); nurse.administerFluVaccine(patient,vaccine);

Slide 62

Slide 62 text

GETTERS AND SETTERS ARE EVIL 62 patient.setShotType(ShotTypes.TYPE_FLU); patient.setDose(dose); patient.setNurse(nurse); … Customer owner = card.getOwner(); if(owner != null && isTrustworthy(owner)){ return false; } … Vaccine vaccine = vaccines. standardAdultFluDose(); nurse.administerFluVaccine(patient,vaccine); card.canBeActivated();

Slide 63

Slide 63 text

GETTERS AND SETTERS ARE EVIL 63 Setters – I haven’t seen a good example. Better to name it like the business action Getters - Do I really need that information outside this object? Don’t autogenerate getters and setters, and think twice before you introduce them

Slide 64

Slide 64 text

What is DDD? Ubiquitous Language Bounded Context Supple Design What’s next? 64

Slide 65

Slide 65 text

What is Supple Design? Supple, as the opposite of stiff Loosely coupled Highly cohesive Able to change Supple Design 65

Slide 66

Slide 66 text

What is Supple Design? Supple, as the opposite of stiff Loosely coupled Highly cohesive Able to change Supple Design 66 Heuristics and Patterns to get to Supple Design

Slide 67

Slide 67 text

But first Supple Design 67

Slide 68

Slide 68 text

COUPLING & COHESION Supple Design 68 Tie Together vs Stick Together

Slide 69

Slide 69 text

COUPLING Supple Design 69 Coupling has to do with change Coupling(a,b,∆) = a∆ -> b∆ for the total correctness of the system Tie Together

Slide 70

Slide 70 text

COUPLING Supple Design 70 Number of classes/microservices Tight Coupling Loose Coupling Tie Together

Slide 71

Slide 71 text

COUPLING Supple Design 71 Degree of Coupling Billing Service Item Tight Coupling Loose Coupling double price = item.getGrossPrice(); TaxRate taxRate = item.getTaxRate(); return price * (1 + (taxRate.percentage() / 100)); Billing Service Item return item.computeNetPrice(); TaxRate TaxRate Tie Together

Slide 72

Slide 72 text

COHESION Supple Design 72 High Cohesion Low Cohesion When one thing changes, all has to change Stick Together

Slide 73

Slide 73 text

COHESION Supple Design 73 Low Cohesion When one thing changes, all has to change. Isn’t that bad? What is the alternative? “Attempting to divide a cohesive class would only result in increased coupling and decreased readability” High Cohesion Stick Together

Slide 74

Slide 74 text

COHESION Supple Design 74 Low Cohesion When one thing changes, all has to change Isn’t that bad? What is the alternative? Cohesion has a lot to do with terms like: • Single Responsibility Principle (SRP) • Separation of Concerns (SoC) High Cohesion Stick Together

Slide 75

Slide 75 text

LOW COUPLING & HIGH COHESION Supple Design 75 Effect on software: • Testability increases (single purpose / less dependencies)

Slide 76

Slide 76 text

LOW COUPLING & HIGH COHESION Supple Design 76 Effect on software: • Testability increases (single purpose / less dependencies) • Maintainability increases / Impact of change decreases (changes are in one place)

Slide 77

Slide 77 text

LOW COUPLING & HIGH COHESION Supple Design 77 Effect on software: • Testability increases (single purpose / less dependencies) • Maintainability increases / Impact of change decreases (changes are in one place) • Reusability increases (Units with a single purpose)

Slide 78

Slide 78 text

BACK TO THE BLUE BOOK Supple Design 78 Heuristics and Patterns to get to Supple Design

Slide 79

Slide 79 text

SUPPLE DESIGN 79 Intention revealing interfaces Side effect free functions Supple Design Heuristics and Patterns to get to Supple Design

Slide 80

Slide 80 text

INTENTION REVEALING INTERFACES When a method name isn’t clear, you have to look inside the method to see what it is for. Or inside the next method it is calling. Or inside the next method it is calling. Or inside the next method it is calling. 80 Supple Design

Slide 81

Slide 81 text

INTENTION REVEALING INTERFACES - Group things that belong together (easier to name) - Name things really well 81 Supple Design

Slide 82

Slide 82 text

INTENTION REVEALING INTERFACES - Group things that belong together (easier to name) - Name things really well chef.prepare(String string) 82 Supple Design

Slide 83

Slide 83 text

INTENTION REVEALING INTERFACES - Group things that belong together (easier to name) - Name things really well chef.prepare(String string) chef.make(Dish dish) 83 Supple Design

Slide 84

Slide 84 text

private Collection totalOrderPrice; private double taxRate; PriceDetails calculatePriceDetails(Item item, int amount) { PriceDetails priceDetails = PriceDetails.of(item, amount, taxRate); totalOrderPrice.add(priceDetails); return priceDetails; } 84 SIDE EFFECT FREE FUNCTIONS Supple Design

Slide 85

Slide 85 text

SIDE EFFECT FREE FUNCTIONS private Collection totalOrderPrice; private double taxRate; PriceDetails calculatePriceDetails(Item item, int amount) { PriceDetails priceDetails = PriceDetails.of(item, amount, taxRate); totalOrderPrice.add(priceDetails); return priceDetails; } 85 Supple Design

Slide 86

Slide 86 text

SIDE EFFECT FREE FUNCTIONS AKA Pure Functions 86 Supple Design

Slide 87

Slide 87 text

SIDE EFFECT FREE FUNCTIONS Why? Can lead to unexpected behavior and is therefore the cause of many bugs WRITE PURE FUNCTIONS WHERE POSSIBLE! 87 Supple Design

Slide 88

Slide 88 text

SIDE EFFECT FREE FUNCTIONS But side effects can’t be prevented • Updating a Database • Calling a Webservice • Sending a message 88 Supple Design

Slide 89

Slide 89 text

SIDE EFFECT FREE FUNCTIONS But side effects can’t be prevented • Updating a Database • Calling a Webservice • Sending a message 89 Note: This mostly happens at the edge of your application. In the domain logic, pure functions can be used a lot Supple Design

Slide 90

Slide 90 text

90 Imperative Shell Functional Core Inside your business logic: • Majority is pure functional code FUNCTIONAL CORE, IMPERATIVE SHELL

Slide 91

Slide 91 text

91 Imperative Shell Functional Core Inside your business logic: • Majority is pure functional code • Code with side-effects in the imperative shell FUNCTIONAL CORE, IMPERATIVE SHELL

Slide 92

Slide 92 text

92 Imperative Shell Functional Core Inside your business logic: • Majority is pure functional code • Code with side-effects in the imperative shell FUNCTIONAL CORE, IMPERATIVE SHELL Direction of dependencies

Slide 93

Slide 93 text

What is DDD? Ubiquitous Language Bounded Context Supple Design What’s next? 93

Slide 94

Slide 94 text

Bounded Context 94 There once was some software for an IT consultancy

Slide 95

Slide 95 text

95 One model for the whole business Bounded Context

Slide 96

Slide 96 text

96 Bounded Context

Slide 97

Slide 97 text

97 So then a bug appeared Bounded Context

Slide 98

Slide 98 text

98 So then a bug appeared Bounded Context

Slide 99

Slide 99 text

99 Different groups had different views (models) Bounded Context

Slide 100

Slide 100 text

100 Different groups had different views (models) IT consultancy Employee - Project - Rate - Level - IBAN - Address - Completed Trainings - Ambitions Bounded Context

Slide 101

Slide 101 text

101 Different groups had different views (models) IT consultancy Employee - Project - Rate - Level - IBAN - Address - Completed Trainings - Ambitions Sales Finance People management HR Bounded Context

Slide 102

Slide 102 text

102 Multiple models are needed. Different problems need different models Bounded Context

Slide 103

Slide 103 text

103 - The boundary within a domain where a particular domain model applies BOUNDED CONTEXT Bounded Context

Slide 104

Slide 104 text

104 - The boundary within a domain where a particular domain model applies - Language driven - Ubiquitous Language is unique per bounded context BOUNDED CONTEXT Bounded Context

Slide 105

Slide 105 text

105 - The boundary within a domain where a particular domain model applies - Language driven - Ubiquitous Language is unique per bounded context - A natural way to split up your model - Strictly consistent within your bounderies - Don´t be distracted or confused by issues outside BOUNDED CONTEXT Bounded Context

Slide 106

Slide 106 text

106 Different groups had different views (models) IT consultancy Employee - Project - Rate - Level - IBAN - Address - Completed Trainings - Ambitions Sales Finance People management HR Bounded Context

Slide 107

Slide 107 text

107 What does that mean for my code Bounded Context

Slide 108

Slide 108 text

108 Bounded Context

Slide 109

Slide 109 text

109 Bounded Context

Slide 110

Slide 110 text

110 DRY vs Coupling across bounded contexts Bounded Context

Slide 111

Slide 111 text

111 DRY vs Coupling across bounded contexts Can’t have both Bounded Context

Slide 112

Slide 112 text

112 DRY very important inside a bounded context Bounded Context

Slide 113

Slide 113 text

113 Reduced coupling more important across bounded contexts Bounded Context

Slide 114

Slide 114 text

114 Autonomy -> Able to evolve alone Bounded Context Reduced coupling more important across bounded contexts

Slide 115

Slide 115 text

115 Autonomy -> Able to evolve alone Decreased cognitive load -> Only have to think about own bounded context Bounded Context Reduced coupling more important across bounded contexts

Slide 116

Slide 116 text

116 Autonomy -> Able to evolve alone Decreased cognitive load -> Only have to think about own bounded context Especially when Bounded Context = Team Bounded Context Reduced coupling more important across bounded contexts

Slide 117

Slide 117 text

117 Bounded Context

Slide 118

Slide 118 text

118 Employee - IBAN - Address - Completed Trainings - Ambitions - Project - Rate - Level Finance People management Sales Is the CEO an employee / consultant? Bounded Context

Slide 119

Slide 119 text

119 Finding bounded contexts Bounded Context

Slide 120

Slide 120 text

120 Bounded Context

Slide 121

Slide 121 text

What is DDD? Ubiquitous Language Bounded Context Supple Design What’s next? 121

Slide 122

Slide 122 text

What’s next? 122 How can I write code like this?!

Slide 123

Slide 123 text

123 “I don’t write clean code from the start, I don’t think anyone could” Uncle Bob REFACTOR What’s next?

Slide 124

Slide 124 text

124 “The moment that the code works, is when you start investing in your career” REFACTOR What’s next?

Slide 125

Slide 125 text

125 PRACTICE MAKES PERFECT What’s next?

Slide 126

Slide 126 text

Thank you! 126