Slide 1

Slide 1 text

Starring With Directed by In the role of Also Starring

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

!

Slide 5

Slide 5 text

@hschwentner Domain-Driven Design

Slide 6

Slide 6 text

@hschwentner #dddesign

Slide 7

Slide 7 text

-DRIVEN DESIGN

Slide 8

Slide 8 text

Java old! C# ABAP PHP Python

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

»Business-Software die Spaß macht«

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

@hschwentner Timetable

Slide 18

Slide 18 text

Workshop Workshop Workshop Workshop Morning Afternoon Not remote

Slide 19

Slide 19 text

Morning Afternoon Wor ksho p Wor ksho p Wor ksho p Wor ksho p Wor ksho p Wor ksho p Wor ksho p

Slide 20

Slide 20 text

@hschwentner Contents

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

@hschwentner #unabsteigbar

Slide 23

Slide 23 text

“Football is a simple gam 22 men chase a ball for 90 minutes and at the e the Germans win.” Gary Lineker Gary Lineker in 2011 by Christophe95 CC BY-SA-3.0

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

Workshop Domain-Driven Design concrete wps.de/ddd

Slide 29

Slide 29 text

Ubiquitous Language

Slide 30

Slide 30 text

Ubiquitous Language Building Blocks Domain Event Aggregate Entity Value Object Bounded Context Strategic Design Context Mapping Collaborative Modeling Domain Expert Event Storming Modeling in Code Domain Storytelling Core Domain Domain Model

Slide 31

Slide 31 text

Microservices CQRS Hexagonal Architecture Agile Event Sourcing Extreme Programming Scrum Cloud Self-Contained Systems Verticals Clean Architecture DevOps AWS Azure Onion Architecture

Slide 32

Slide 32 text

@hschwentner Structure

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

04.03.25 //// Seite 72 WPS – Workplace Solutions DOMÄNE DOMÄNE

Slide 35

Slide 35 text

Java old! C# ABAP PHP Python

Slide 36

Slide 36 text

@hschwentner You

Slide 37

Slide 37 text

Programming Languages My Questions My life as a developer My experiences using DDD My wishes regarding the training family My first computer

Slide 38

Slide 38 text

Story Time

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Grafik: Robert Gloth/Wikipedia

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Foto: Serge Melki/Wikipedia

Slide 44

Slide 44 text

Foto: Public Domain/Wikipedia

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

@hschwentner How is that supposed to work?

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

Foto: Henning Schwentner

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Detail: Depth

Slide 52

Slide 52 text

Detail: Tiefenzahl

Slide 53

Slide 53 text

Foto: Afrank99/Wikipedia

Slide 54

Slide 54 text

Foto: Henning Schwentner

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

PUTS NAVIGATING OFFICER CAPTAIN ASKS FOR 7 SHIP SILHOUETTE ON CARTO- GRAPHER SOUNDING SHIP DEPTH MEASURES 1 SENDS 2 TO CALCULATES 3 DRAW S 4 SENDS 5 DEPTH MAP TO MOVES & TURNS 8 SHIP SILHOUETTE TO FIND 9 DISCUSSES WITH 6 ROUTE ROUTE DEPTH MAP DEPTH MAP DEPTH (RAW) ROUTE CONTOUR LINES

Slide 61

Slide 61 text

@hschwentner Is There an App for It?

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

CYBER

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

@hschwentner So!ware != End in itself

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

?

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

IMPORTANT!

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

So#ware Domain

Slide 78

Slide 78 text

Foto: Rosie the Riveter/Wikimedia/CC-PD-Mark

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

Domain Knowledg e Foto: Rosie the Riveter/Wikimedia/CC-PD-Mark

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

Groß Klein

Slide 83

Slide 83 text

Collaborative Modeling

Slide 84

Slide 84 text

Domain Expert Developer

Slide 85

Slide 85 text

Knowledge crunching

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

@hschwentner Methods

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

https://domainstorytelling.org

Slide 90

Slide 90 text

LANGUAGE

Slide 91

Slide 91 text

Fach- sprache Domain Expert Developer

Slide 92

Slide 92 text

=> direct commu- nication telephone game to user dev user dev

Slide 93

Slide 93 text

Ludwig Wi)genstein “Whereof one cannot speak, thereof one must be silent.”

Slide 94

Slide 94 text

Ludwig Wi)genstein »Wovon man nicht sprechen kann, darüber muss man schweigen.«

Slide 95

Slide 95 text

Depth Scale Silhouette Marking Depth Map to move to measure run aground neon yellow

Slide 96

Slide 96 text

Ubiquitous Language

Slide 97

Slide 97 text

Jubikjutuss Lengwitsch

Slide 98

Slide 98 text

PUTS NAVIGATING OFFICER CAPTAIN ASKS FOR 7 SHIP SILHOUETTE ON CARTO- GRAPHER SOUNDING SHIP DEPTH MEASURES 1 SENDS 2 TO CALCULATES 3 DRAW S 4 SENDS 5 DEPTH MAP TO MOVES & TURNS 8 SHIP SILHOUETTE TO FIND 9 DISCUSSES WITH 6 ROUTE ROUTE DEPTH MAP DEPTH MAP DEPTH (RAW) ROUTE CONTOUR LINES

Slide 99

Slide 99 text

SMALL

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

class Silhouette { //... }

Slide 102

Slide 102 text

No content

Slide 103

Slide 103 text

class Silhouette { public void moveBy(Length length) //... }

Slide 104

Slide 104 text

No content

Slide 105

Slide 105 text

class Silhouette { public void moveBy(Length length) //... public void turnBy(Angle angle) //... }

Slide 106

Slide 106 text

Erich Gamma “Program to an interface, not to an implementa@on”

Slide 107

Slide 107 text

class Silhouette { public void setPosition(Position p) //... } ✘

Slide 108

Slide 108 text

Slide 109

Slide 109 text

WARNING SETTERS CAUSE MODEL ANEMIA

Slide 110

Slide 110 text

MOVES & TURNS 8 SHIP SILHOUETTE TO FIND ROUTE NAUTICAL OFFICER «En$ty» Silhoue(e move() turn()

Slide 111

Slide 111 text

Tactical Design

Slide 112

Slide 112 text

No content

Slide 113

Slide 113 text

Entity

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

import org.jmolecules.ddd.annotation.*; @Entity public class DepthMap { //... }

Slide 116

Slide 116 text

Value Object

Slide 117

Slide 117 text

Example: Depth

Slide 118

Slide 118 text

import org.jmolecules.ddd.annotation.*; @ValueObject public record Depth(/* ... */)

Slide 119

Slide 119 text

Domain Event

Slide 120

Slide 120 text

MANEUVER PLANNING DEPTHS SOUNDING DEPTH MAP COMPLETED

Slide 121

Slide 121 text

BIG

Slide 122

Slide 122 text

Foto: Rosie the Riveter/Wikimedia/CC-PD-Mark

Slide 123

Slide 123 text

Foto: Rosie the Riveter/Wikimedia/CC-PD-Mark

Slide 124

Slide 124 text

No content

Slide 125

Slide 125 text

No content

Slide 126

Slide 126 text

No content

Slide 127

Slide 127 text

!

Slide 128

Slide 128 text

No content

Slide 129

Slide 129 text

No content

Slide 130

Slide 130 text

Bounded Context

Slide 131

Slide 131 text

!

Slide 132

Slide 132 text

PUTS NAVIGATING OFFICER CAPTAIN ASKS FOR 7 SHIP SILHOUETTE ON CARTO- GRAPHER SOUNDING SHIP DEPTH MEASURES 1 SENDS 2 TO CALCULATES 3 DRAW S 4 SENDS 5 DEPTH MAP TO MOVES & TURNS 8 SHIP SILHOUETTE TO FIND 9 DISCUSSES WITH 6 ROUTE ROUTE DEPTH MAP DEPTH MAP DEPTH (RAW) ROUTE CONTOUR LINES DEPTH MEASURE- MENT MANEUVER PLANNING

Slide 133

Slide 133 text

TIDAL FORE- CAST MANEUVER PLANNING DEPTH MEASUREMENT

Slide 134

Slide 134 text

Ubiquitous Language

Slide 135

Slide 135 text

No content

Slide 136

Slide 136 text

WPS – Workplace Solutions #dddkonkret www.wps.de COLLABORATIVE MODELING Domain-Driven Design concrete

Slide 137

Slide 137 text

04.03.25 //// Seite 242 WPS – Workplace Solutions INHALT DOMÄNE DOMÄNE

Slide 138

Slide 138 text

No content

Slide 139

Slide 139 text

Collaborative Modeling

Slide 140

Slide 140 text

Collaborative Modeling

Slide 141

Slide 141 text

https://www.domainstorytelling.org

Slide 142

Slide 142 text

LEGT NAUTIKER KAPITÄN FRAGT NACH 7 SCHIFFS- SILHOUETTE AUF PEILDIENST PEILSCHIFF TIEFE PEILT 1 SENDET 2 AN BERECHNET 3 ERZ EUGT 4 SENDET 5 PEILPLAN AN VERSCHIEBT & DREHT 8 SCHIFFS- SILHOUETTE UND FINDET 9 MELDET AN 6 ROUTE ROUTE PEILPLAN PEILPLAN TIEFEN- ZAHLEN ROUTE TIEFENLINIEN

Slide 143

Slide 143 text

No content

Slide 144

Slide 144 text

No content

Slide 145

Slide 145 text

No content

Slide 146

Slide 146 text

No content

Slide 147

Slide 147 text

@hschwentner Explained

Slide 148

Slide 148 text

@hschwentner Domain Storytelling = Pictographic Language + Workshop Format

Slide 149

Slide 149 text

@hschwentner The Workshop Format

Slide 150

Slide 150 text

@hschwentner The right people

Slide 151

Slide 151 text

No content

Slide 152

Slide 152 text

Storyteller Listeners ! !

Slide 153

Slide 153 text

No content

Slide 154

Slide 154 text

No content

Slide 155

Slide 155 text

@hschwentner DEPTH MAP HANDS OVER NAUTICAL OFFICER CARTOGRAPHE R TO “The cartographer sends the depth map to the nautical officer” SENDS

Slide 156

Slide 156 text

Active Listening

Slide 157

Slide 157 text

CONCRETE STORIES VS. ABSTRACT PROCESSES

Slide 158

Slide 158 text

@hschwentner The Pictographic Language

Slide 159

Slide 159 text

@hschwentner ßDraw here Leave some empty space there à Comments Assump5ons Name of the Domain Story

Slide 160

Slide 160 text

@hschwentner actor work object ac5vity 5 sequence number

Slide 161

Slide 161 text

@hschwentner SHIP SILHOUETTE CAPTAIN MOVES

Slide 162

Slide 162 text

@hschwentner A w works on A v hands over using w B to A collaborates on w B collaborates on

Slide 163

Slide 163 text

@hschwentner DRAWS MEASURES DEPTH DEPTH MAP

Slide 164

Slide 164 text

@hschwentner SENDS DRAWS DEPTH MAP DEPTH MAP

Slide 165

Slide 165 text

@hschwentner person group IT system

Slide 166

Slide 166 text

ACTORS ONCE/ WORK OBJECTS SEVERAL TIMES PUTS NAUTICAL OFFICER 7 SHIP SILHOUETTE MOVES & TURNS 8 SHIP SILHOUETTE

Slide 167

Slide 167 text

PICTOGRAPHIC LANGUAGE – NO IF/SWITCH/OR actor work object ac5vity 5 sequence number

Slide 168

Slide 168 text

Scenario-based modeling

Slide 169

Slide 169 text

Scenarios Maneuver Planning – The Happy Path Maneuver Planning – Storm Flooding Expected Maneuver Planning – All Berths Full

Slide 170

Slide 170 text

@hschwentner Scope

Slide 171

Slide 171 text

Scope Factors

Slide 172

Slide 172 text

@hschwentner Granularity Point in time Domain Purity

Slide 173

Slide 173 text

Granularity fine- grained coarse- grained x x x x x x x x x x x x x x x x x x

Slide 174

Slide 174 text

@hschwentner A Day at the Beach " Sea Level # Kite Level ☁ Cloud Level % Fish Level & Clam Level Foto: Dennis Hamilton/flickr/CC BY 2.0 Alistair Cockburn

Slide 175

Slide 175 text

Point in Time as-is to-be t

Slide 176

Slide 176 text

Point in Time now optimized t with new system

Slide 177

Slide 177 text

Domain Purity pure digitalized

Slide 178

Slide 178 text

@hschwentner Tools

Slide 179

Slide 179 text

No content

Slide 180

Slide 180 text

PowerPoint

Slide 181

Slide 181 text

@hschwentner

Slide 182

Slide 182 text

https://www.wps.de/modeler/ • https://egon.io

Slide 183

Slide 183 text

@hschwentner Purposes

Slide 184

Slide 184 text

@hschwentner draw boundaries learn language work on requirements implement domain model find shadow IT …

Slide 185

Slide 185 text

@hschwentner More on Domain Storytelling

Slide 186

Slide 186 text

No content

Slide 187

Slide 187 text

https://hschwentner.io Read on in:

Slide 188

Slide 188 text

04.03.25 //// Seite 338 WPS – Workplace Solutions EXERCISE: Domain Storytelling in Groups

Slide 189

Slide 189 text

May 6th-9th 2024 Vienna, Austria The Collaborative Modeling Unconference comocamp.org Event Storming User Story Mapping Event Modeling Impact Mapping Domain Storytelling Storystorming Context Mapping Example Mapping etc.

Slide 190

Slide 190 text

WPS – Workplace Solutions #dddkonkret www.wps.de STRATEGIC DESIGN Domain-Driven Design concrete

Slide 191

Slide 191 text

04.03.25 //// Seite 341 WPS – Workplace Solutions ÜBERSICHT DOMÄNE DOMÄNE

Slide 192

Slide 192 text

?

Slide 193

Slide 193 text

?

Slide 194

Slide 194 text

No content

Slide 195

Slide 195 text

No content

Slide 196

Slide 196 text

No content

Slide 197

Slide 197 text

No content

Slide 198

Slide 198 text

No content

Slide 199

Slide 199 text

?

Slide 200

Slide 200 text

?

Slide 201

Slide 201 text

No content

Slide 202

Slide 202 text

@hschwentner “Whoever uses a canonical model has lost control over his life.” – Karl Lagerfeld

Slide 203

Slide 203 text

@hschwentner »Wer ein unternehmensweites Domänenmodell einsetzt, hat die Kontrolle über sein Leben verloren« – Karl Lagerfeld

Slide 204

Slide 204 text

No content

Slide 205

Slide 205 text

!

Slide 206

Slide 206 text

No content

Slide 207

Slide 207 text

!

Slide 208

Slide 208 text

No content

Slide 209

Slide 209 text

No content

Slide 210

Slide 210 text

No content

Slide 211

Slide 211 text

No content

Slide 212

Slide 212 text

Bounded Context

Slide 213

Slide 213 text

!

Slide 214

Slide 214 text

Movement Cosme*cs ! Emo*ons

Slide 215

Slide 215 text

PUTS NAVIGATING OFFICER CAPTAIN ASKS FOR 7 SHIP SILHOUETTE ON CARTO-GRAPHER SOUNDING SHIP DEPTH MEASURES 1 SENDS 2 TO CALCULATES 3 DRAW S 4 SENDS 5 DEPTH MAP TO MOVES & TURNS 8 SHIP SLHOETTE TO FIND 9 DISCUSSES WITH 6 ROUTE ROUTE DEPTH MAP DEPTH MAP DEPTH (RAW) ROUTE CONTOUR LINES DEPTH MEASURE- MENT MANEUVER PLANNING

Slide 216

Slide 216 text

@hschwentner Another Example

Slide 217

Slide 217 text

No content

Slide 218

Slide 218 text

No content

Slide 219

Slide 219 text

@hschwentner Do I get a car for this?

Slide 220

Slide 220 text

No content

Slide 221

Slide 221 text

04.03.25 //// Seite 371 WPS – Workplace Solutions

Slide 222

Slide 222 text

04.03.25 //// Seite 372 WPS – Workplace Solutions

Slide 223

Slide 223 text

CUSTOMER TELLS WISH FOR 1 SALES- PERSON SIGNS TO GIVES FOR CONTRACT 3 RISK MANAGER CONTRACT PASSES ON TO 4 CONTRACT VO TES CHECKS CALCU LATES 5 6 7 CALCU- LATES TO 8 2 CAR CREDIT RATING INSTALLMENT CAR RESALE VALUE CONTRACT

Slide 224

Slide 224 text

CUSTOMER SIGNS CONTRACT 3 RISK MANAGER CONTRACT VOTES 7 «Entity» Contract sign() vote()

Slide 225

Slide 225 text

«Entity» Contract sign() vote()

Slide 226

Slide 226 text

«Entity» Contract sign() vote() extend() terminate() sell_to_refinance() …

Slide 227

Slide 227 text

BBOM Foto: Benutzer:Summi/Wikipedia/CC-BY-SA-3.0-migrated

Slide 228

Slide 228 text

No content

Slide 229

Slide 229 text

No content

Slide 230

Slide 230 text

@hschwentner Why is that?

Slide 231

Slide 231 text

No content

Slide 232

Slide 232 text

No content

Slide 233

Slide 233 text

@hschwentner Too big to be understood as a whole

Slide 234

Slide 234 text

No content

Slide 235

Slide 235 text

No content

Slide 236

Slide 236 text

04.03.25 //// Seite 386 WPS – Workplace Solutions CUSTOMER TELLS WISH FOR 1 SALES- PERSON SIGNS TO GIVES FOR CONTRACT 3 RISK MANAGER CONTRACT PASSES ON TO 4 CONTRACT VOTES CHECKS CALCULATES 5 6 7 CALCU- LATES TO 8 2 CAR CREDIT RATING INSTALLMENT CAR RESALE VALUE CONTRACT SALES RISK ASSESSMENT

Slide 237

Slide 237 text

«En$ty» Contract sign() vote() ✘

Slide 238

Slide 238 text

«En$ty» Contract sign() «En$ty» Contract vote()

Slide 239

Slide 239 text

«En$ty» Contract sign() vote() ✘

Slide 240

Slide 240 text

«En$ty» Contract sign() «En$ty» Contract vote()

Slide 241

Slide 241 text

«En$ty» Contract sign() «En$ty» Contract vote() SALES RISK ASSESSMENT

Slide 242

Slide 242 text

04.03.25 //// Seite 392 WPS – Workplace Solutions Common heuristics: § Points of no Return (persistent work results) § Boundaries within the process § State changes, that affect the “nature” of a work object (e.g. “contract legally binding,” “shopping cart ordered”) § Departments of the organisation § Contextual language § Different usage of work objects § Triggers at different points in time § NOT: by work objects! HOW TO CUT THE DOMAIN? Foto: Wikipedia/PD-ScottForesman

Slide 243

Slide 243 text

04.03.25 //// Seite 393 WPS – Workplace Solutions

Slide 244

Slide 244 text

04.03.25 //// Seite 394 WPS – Workplace Solutions Team Head Team Tail Team Body Team Legs

Slide 245

Slide 245 text

04.03.25 //// Seite 395 WPS – Workplace Solutions Team Emma Team Berta Team Erna Team Lisl

Slide 246

Slide 246 text

@hschwentner Code Database Team

Slide 247

Slide 247 text

@hschwentner Drawing Boundaries with Domain Storytelling

Slide 248

Slide 248 text

@hschwentner Scope: coarse-grained to-be (optimized) pure

Slide 249

Slide 249 text

Which activities belong together (from an actor’s perspective)?

Slide 250

Slide 250 text

CUSTOMER TELLS WISH FOR 1 SALESPERSON SIGNS TO GIVES FOR CONTRACT 3 RISK MANAGER CONTRACT PASSES ON TO 4 CONTRACT VO TES CHECKS CALCU LATES 5 6 7 CALCU- LATES TO 8 2 CAR CREDIT RATING INSTALLMENT CAR RESALE VALUE CONTRACT SALES RISK ASSESSMENT

Slide 251

Slide 251 text

CUSTOMER TELLS WISH FOR 1 SALESPERSON SIGNS TO GIVES FOR CONTRACT 3 RISK MANAGER CONTRACT PASSES ON TO 4 CONTRACT VO TES CHECKS CALCU LATES 5 6 7 CALCU- LATES TO 8 2 CAR CREDIT RATING INSTALLMENT CAR RESALE VALUE CONTRACT SALES Group the sentences • Boundary around activites and work objects • Keep actors outside boundaries Give a name to the group RISK ASSESSMENT

Slide 252

Slide 252 text

@hschwentner Naming Subdomains Express what is done Verbs turned into nouns Often: -ing-form Anti-pattern: name of work object as name for subdomain

Slide 253

Slide 253 text

@hschwentner Naming Subdomains— Examples Price calculation Risk assess- ment Maneuver planning Customer Car Price Payment Car inspection

Slide 254

Slide 254 text

Indicators: 1) Actor produces result on their own 2) One-way informa

Slide 255

Slide 255 text

@hschwentner Drawing Boundaries in Existing Sofware a.k.a.: How to split the monolith

Slide 256

Slide 256 text

@hschwentner Strategic Transformation 1. Step: Domain re-discovery 2. Step: Modeling the to-be 3. Step: Aligning as-is with to-be 4. Step: Do the move

Slide 257

Slide 257 text

https://hschwentner.io Read on in: https://hschwentner.io/domain-driven-refactorings

Slide 258

Slide 258 text

04.03.25 //// Seite 421 WPS – Workplace Solutions EXERCISE: Find Bounded Contexts

Slide 259

Slide 259 text

04.03.25 //// Seite 422 WPS – Workplace Solutions BOUNDED CONTEXTS FÜR DAS KINO ABLAUF- PLANUNG KARTEN- VERKAUF BUCH- HALTUNG

Slide 260

Slide 260 text

04.03.25 //// Seite 444 WPS – Workplace Solutions AND NOW? § Core vs Supporting § Event Storming § Taktisches Design § Code/LeasingNinja § Hexagonal/Onion Architecture § Context Mapping § How to split the monolith

Slide 261

Slide 261 text

@hschwentner How to split the monolith

Slide 262

Slide 262 text

1) How should it be? 2) How is it? 3) How to move the “is” to the “ideal”? RISK MANAGE- MENT SALES

Slide 263

Slide 263 text

1) How should it be? 1) Domain Re-Discovery 2) “ideal” context map 2) How is it? 1) Architecture Analysis 2) As-is context map 3) How to move the “is” to the “ideal”? 1) Compare 2) Create List of Refactorings 4) Do the move 1) Extract a suppor

Slide 264

Slide 264 text

old old old old new new new new “just flip the lever” 1 2 3 4 5 a.k.a. big bang replacement

Slide 265

Slide 265 text

old old old new new new new 2 3 4 5 old 1

Slide 266

Slide 266 text

Strangler Fig Application

Slide 267

Slide 267 text

Strangler Fig Application

Slide 268

Slide 268 text

Lesson: is better than Strangler Fig Application Big Bang Replacement

Slide 269

Slide 269 text

<> Contract sign() SALES RISK ASSESSMENT <> Contract sign() vote() … BIG BALL OF MUD <> Contract vote()

Slide 270

Slide 270 text

https://hschwentner.io Read on in: h#ps://hschwentner.io/domain-driven-refactorings

Slide 271

Slide 271 text

Read on: h#ps://hschwentner.io/domain-driven-refactorings

Slide 272

Slide 272 text

@hschwentner Always Microservices?

Slide 273

Slide 273 text

Simon Brown

Slide 274

Slide 274 text

Distributed Big Ball Of Mud Modulith Microservices Monolithic Big Ball Of Mud

Slide 275

Slide 275 text

No content

Slide 276

Slide 276 text

@hschwentner Consulting

Slide 277

Slide 277 text

04.03.25 //// Seite 525 WPS – Workplace Solutions § Subdomänen § Kern (Core Domain) § Unterstützende (Supporting Domain) § Allgemeine (Generic Domain) § Context Mapping § Shared Kernel § Customer/Supplier § Open-Host-Service § Published Language § Separate Ways § Anticorruption Layer § Conformist STRATEGISCHES DESIGN – WEITERE BEGRIFFE

Slide 278

Slide 278 text

WPS – Workplace Solutions #dddkonkret www.wps.de TACTICAL DESIGN Domain-Driven Design concrete

Slide 279

Slide 279 text

04.03.25 //// Seite 579 WPS – Workplace Solutions OVERVIEW DOMÄNE DOMÄNE

Slide 280

Slide 280 text

04.03.25 //// Seite 580 WPS – Workplace Solutions ARCHITECTURE WITH BOUNDED CONTEXTS TIDAL FORECAST MANEUVER PLANNING DEPTHS MEASUREMENT

Slide 281

Slide 281 text

04.03.25 //// Seite 581 WPS – Workplace Solutions ARCHITECTURE WITHIN A BOUNDED CONTEXT MANEUVER PLANNING User Interface Application Domain Infrastructure

Slide 282

Slide 282 text

04.03.25 //// Seite 582 WPS – Workplace Solutions DOMAIN-DRIVEN DESIGN—LAYERED ARCHITECTURE § User interface layer § Receives input and user commands and presents information. § Application layer (Fowler: Service Layer) § Describes and coordinates application processes. § Domain layer § Represents the business domain logic. § Infrastructure layer § Provides technical services such as persistence or communication with other systems. User Interface Application Domain Infrastructure

Slide 283

Slide 283 text

04.03.25 //// Seite 583 WPS – Workplace Solutions LAYERED ARCHITECTURE – CRITIQUE MANEUVER PLANNING § Domain layer is linked to the database layer § Technology “bubbles up” into domain layer § No clean separation of domain & technology Alistair Cockburn Foto: Fotograf Dennis Hamilton/Alistair Cockburn/flickr/CC BY 2.0 User Interface Application Domain Infrastructure

Slide 284

Slide 284 text

04.03.25 //// Seite 584 WPS – Workplace Solutions below above FROM ABOVE/BELOW TO INSIDE/OUTSIDE out- side inside

Slide 285

Slide 285 text

04.03.25 //// Seite 585 WPS – Workplace Solutions port port HEXAGONAL ARCHITECTURE Foto: Dennis Hamilton/flickr/CC BY 2.0 http://alistair.cockburn.us/Hexagonal%2Barchitecture adapter adapter Alistair Cockburn

Slide 286

Slide 286 text

04.03.25 //// Seite 586 WPS – Workplace Solutions KINDS OF PORTS - For UI etc. - Methods to be called - “from above” - For DB and infrastructure - Interfaces to be implemented - “from below”

Slide 287

Slide 287 text

04.03.25 //// Seite 587 WPS – Workplace Solutions ONION ARCHITECTURE U I “application core” domain services domain model infra app ture struc serv lication ices Jeffrey Palermo !

Slide 288

Slide 288 text

04.03.25 //// Seite 588 WPS – Workplace Solutions CLEAN ARCHITECTURE Robert C. Martin ”Uncle Bob“

Slide 289

Slide 289 text

04.03.25 //// Seite 589 WPS – Workplace Solutions ARCHITECTURE HAMBURGER Application Domain Infrastructure UI coarse grained Henning Schwentner !

Slide 290

Slide 290 text

04.03.25 //// Seite 590 WPS – Workplace Solutions THE BASIC IDEA OF OBJECT-ORIENTATION: A SOFTWARE-TECHNICAL MODEL BASED ON DOMAIN OBJECTS

Slide 291

Slide 291 text

04.03.25 //// Seite 591 WPS – Workplace Solutions FROM DOMAIN STORY TO DOMAIN MODEL Silhouette MOVES SILHOUETTE NAUTICAL OFFICER LENGTH Length moveBy(:Length) BY 8

Slide 292

Slide 292 text

EXERCISE: BUILD DOMAIN MODEL FROM DOMAIN STUDIES IN CASE STUDY

Slide 293

Slide 293 text

04.03.25 //// Seite 593 WPS – Workplace Solutions En##es Value Objects Aggregates Services Factories Repositories

Slide 294

Slide 294 text

04.03.25 //// Seite 594 WPS – Workplace Solutions DOMAIN TERMS – WHAT IS STRIKING? insurance policy vacation request building activity purchase contract order zip code GPS coordinate IBAN container number IATA code

Slide 295

Slide 295 text

04.03.25 //// Seite 596 WPS – Workplace Solutions ENTITIES § Objects of a domain that the user works with. § The results of the work are reflected by their state! § Can be composed of other entities. § Have an (immutable) identity. § Maintain their own consistency and integrity! § Have a clearly defined life cycle. § Have a (mostly mutable) state. § Describe their state by value objects. § Synonyms: Business Object / Domain Object / Work Material § NOT TO BE confused with the term “ENTITY” from Entity-Relationship-Model! Foto: Bundesrepublik Deutschland/Wikipedia/PD Germany Foto: Kaz/pixabay/CC0 Foto: Thomas G./Wikipedia/CC BY-SA 3.0 Foto: OpenClipart-Vectors/pixabay/CC0

Slide 296

Slide 296 text

No content

Slide 297

Slide 297 text

04.03.25 //// Seite 598 WPS – Workplace Solutions ENTITIES «Entity» DepthMap depthMapId mark(Marking)

Slide 298

Slide 298 text

04.03.25 //// Seite 600 WPS – Workplace Solutions VALUE OBJECTS § Value objects are symbols for values of a certain type in the domain. § Symbolize the same value if they are equal. § They are not edited by the user and cannot be modified. § Can be calculated (from other value objects), if necessary. § Can consist of other value objects, but never of entities! ValueObject 2.5 ValueObject ValueObject ValueObject ValueObject two and a half

Slide 299

Slide 299 text

Depth Diameter Position

Slide 300

Slide 300 text

04.03.25 //// Seite 603 WPS – Workplace Solutions VALUE OBJECTS «Value Object» Depth centimeters : int equals()

Slide 301

Slide 301 text

04.03.25 //// Seite 606 WPS – Workplace Solutions EXERCISE: ENTITES, VALUE OBJECTS

Slide 302

Slide 302 text

04.03.25 //// Seite 607 WPS – Workplace Solutions ENTITIES UND VALUE OBJECTS IM KARTENVERKAUF Saalplan • Anzahl Plätze suchen • Verkaufte Plätze mark. • Reserv. Plätze mit RN markieren Vorstellung • Datum • Zeitraum • Film Reservierungs -nummer Kinokarte • Mit Platz beschriften • Vorstellung Saalplanstapel • Saalplan zu Vorst. Holen • Saalplan zurücklegen Liste der Reservierungsnummern • Reservierungsnummer abholen • Name+Vorst. Vermerken • Vorst. Mit RN heraussuchen Film • Titel • Regisseur, Schauspieler • Freigabe • Spieldauer Platz/Sitzplatz • Reihe • Nummer Saal/Kinosaal • Kapazität • Anzahl Reihen VO Entity Entity Entity Entity Entity Entity

Slide 303

Slide 303 text

04.03.25 //// Seite 608 WPS – Workplace Solutions ENTITIES UND VALUE OBJECTS IM KARTENVERKAUF Saalplan • Anzahl Plätze suchen • Verkaufte Plätze mark. • Reserv. Plätze mit RN markieren Vorstellung • Datum • Zeitraum • Film Reservierungs -nummer Liste der Reservierungsnummern • Reservierungsnummer abholen • Name+Vorst. Vermerken • Vorst. Mit RN heraussuchen Film • Titel • Regisseur, Schauspieler • Freigabe • Spieldauer Platz/Sitzplatz • Reihe • Nummer Saal/Kinosaal • Kapazität • Anzahl Reihen VO Entity Entity Entity Entity Entity Entity

Slide 304

Slide 304 text

WPS – Workplace Solutions #dddkonkret www.wps.de REPOSITORIES AND AGGREGATES

Slide 305

Slide 305 text

04.03.25 //// Seite 610 WPS – Workplace Solutions REPOSITORIES § Are the access points to the aggregates! § Encapsulate the technical details of the technical infrastructure layer ... § ... and map external data to entities and value objects. § Store aggregates (e. g. in databases). Repository Aggregate Aggregate Aggregate Aggregate Aggregate

Slide 306

Slide 306 text

04.03.25 //// Seite 611 WPS – Workplace Solutions REPOSITORY @ HAMBURG PORT: THE DEPTH MAP CABINET

Slide 307

Slide 307 text

04.03.25 //// Seite 612 WPS – Workplace Solutions REPOSITORY: TWO PART IMPLEMENTATION «Repository Interface» DepthMapCabinet getDepthMap(Area, Scale) : DepthMap putBack(DepthMap) «Repository Implementation» MySQLDepthMapCabinet

Slide 308

Slide 308 text

04.03.25 //// Seite 613 WPS – Workplace Solutions AGGREGATES § Aggregates are entities that are relevant in themselves (and not just as part of another entity). § Protect the consistency and integrity of their inner entities. § They don't necessarily have to hide them to do this! § Always have a designated entity as an entry point (root). § Usually stored. § As a whole! § Not necessarily in a relational way! Root Entity VO VO VO Aggregate

Slide 309

Slide 309 text

04.03.25 //// Seite 614 WPS – Workplace Solutions AGGREGATES § Actually, the value objects are outside as they are immutable and may be reused anywhere. Root Entity VO VO VO Some other object Aggregate

Slide 310

Slide 310 text

04.03.25 //// Seite 615 WPS – Workplace Solutions AGGREGATES § An aggregate can consist of many entities. Root Entity Entity Entity Entity Entity VO VO VO VO VO VO VO VO VO VO VO Aggregate

Slide 311

Slide 311 text

No content

Slide 312

Slide 312 text

04.03.25 //// Seite 617 WPS – Workplace Solutions Aggregate «Aggregate Root» DepthMap «Entity» Marking «Value Object» Depth

Slide 313

Slide 313 text

04.03.25 //// Seite 618 WPS – Workplace Solutions ENTITIES UND VALUE OBJECTS IM KARTENVERKAUF Saalplan • Anzahl Plätze suchen • Verkaufte Plätze mark. • Reserv. Plätze mit RN markieren Vorstellung • Datum • Zeitraum • Film Reservierungs -nummer Liste der Reservierungsnummern • Reservierungsnummer abholen • Name+Vorst. Vermerken • Vorst. Mit RN heraussuchen Film • Titel • Regisseur, Schauspieler • Freigabe • Spieldauer Platz/Sitzplatz • Reihe • Nummer Saal/Kinosaal • Kapazität • Anzahl Reihen VO Entity Entity Entity Entity Entity Entity

Slide 314

Slide 314 text

EXERCISE: DRAW AGGREGATE BOUNDARIES. WHICH REPOSITORIES DO WE NEED?

Slide 315

Slide 315 text

04.03.25 //// Seite 620 WPS – Workplace Solutions ENTITIES UND VALUE OBJECTS IM KARTENVERKAUF Saalplan • Anzahl Plätze suchen • Verkaufte Plätze mark. • Reserv. Plätze mit RN markieren Vorstellung • Datum • Zeitraum • Film Reservierungs -nummer Liste der Reservierungsnummern • Reservierungsnummer abholen • Name+Vorst. Vermerken • Vorst. Mit RN heraussuchen Film • Titel • Regisseur, Schauspieler • Freigabe • Spieldauer Platz/Sitzplatz • Reihe • Nummer Saal/Kinosaal • Kapazität • Anzahl Reihen VO Entity Entity Wurzel-Entity Entity Entity Entity Aggregate Aggregate Aggregate Aggregate Aggregate

Slide 316

Slide 316 text

04.03.25 //// Seite 637 WPS – Workplace Solutions ARCHITECTURE HAMBURGER fine grained model repository interface controller use case service entity value object view data model repository implementation widget library REST frame- work transaction handling domain library programming language ORM file system access domain event

Slide 317

Slide 317 text

WPS – Workplace Solutions #dddkonkret www.wps.de IMPLEMENTING THE BUILDING BLOCKS IN JAVA Domain-Driven Design concrete

Slide 318

Slide 318 text

04.03.25 //// Seite 640 WPS – Workplace Solutions

Slide 319

Slide 319 text

04.03.25 //// Seite 641 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT public class Account { }

Slide 320

Slide 320 text

04.03.25 //// Seite 642 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT import org.jmolecules.ddd.annotation.Entity; @Entity public class Account { }

Slide 321

Slide 321 text

04.03.25 //// Seite 643 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT import org.jmolecules.ddd.annotation.Entity; @Entity public class Account { }

Slide 322

Slide 322 text

04.03.25 //// Seite 644 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT @Entity public class Account { private int _balance; public int getBalance() { return _balance; } public void setBalance(int balance) { _balance = balance; } } ✘ Bad: The account balance can be set to any value

Slide 323

Slide 323 text

04.03.25 //// Seite 645 WPS – Workplace Solutions A BANK ACCOUNT—SECOND VERSION @Entity public class Account { private int _balance; public int balance() { return _balance; } public void deposit(int amount) { _balance += amount; } public void withdraw(int amount) { _balance -= amount; } } Better: Operations with domain-specific behavior and names

Slide 324

Slide 324 text

04.03.25 //// Seite 646 WPS – Workplace Solutions A BANK ACCOUNT—THIRD VERSION @Entity public class Account { private int _balance; public int balance() { return _balance; } public void deposit(int amount) { _balance += amount; } public void withdraw(int amount) { if (amount > balance()) { throw new IllegalArgumentException("Amount too big"); } _balance -= amount; } Even better: Preconditions can be checked

Slide 325

Slide 325 text

04.03.25 //// Seite 648 WPS – Workplace Solutions DESIGN BY CONTRACT Foto: Urheber Fuchsias/Bertrand Meyer/Wikipedia/CC BY-SA 4.0

Slide 326

Slide 326 text

04.03.25 //// Seite 649 WPS – Workplace Solutions A BANK ACCOUNT—DESIGN BY CONTRACT USING “ASSERT” @Entity public class Account { // ... public void withdraw(int amount) { assert amount <= balance(); _balance -= amount; } } Assertion using keyword assert

Slide 327

Slide 327 text

04.03.25 //// Seite 650 WPS – Workplace Solutions A BANK ACCOUNT—DESIGN BY CONTRACT USING “VALID4J” import static org.valid4j.Assertive.*; @Entity public class Account { // ... public void withdraw(int amount) { require(amount <= balance()); _balance -= amount; } } Hamcrest matchers can be used

Slide 328

Slide 328 text

04.03.25 //// Seite 654 WPS – Workplace Solutions GREAT, BUT… @Entity public class Account { // ... public void withdraw(int amount) { assert amount <= balance(); _balance -= amount; } } Can I withdraw a negative amount? In EUR or GBP or…?

Slide 329

Slide 329 text

04.03.25 //// Seite 656 WPS – Workplace Solutions AN AMOUNT TYPE public class Amount { }

Slide 330

Slide 330 text

04.03.25 //// Seite 657 WPS – Workplace Solutions AN AMOUNT TYPE import org.jmolecules.ddd.annotation.ValueObject; @ValueObject public class Amount { }

Slide 331

Slide 331 text

04.03.25 //// Seite 658 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public class Amount { private int _amount; private Currency _currency; }

Slide 332

Slide 332 text

04.03.25 //// Seite 659 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public class Amount { private final int _amount; private final Currency _currency; }

Slide 333

Slide 333 text

04.03.25 //// Seite 660 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public class Amount { private final int _amount; private final Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } }

Slide 334

Slide 334 text

04.03.25 //// Seite 661 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public class Amount { private final int _amount; private final Currency _currency; private Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } public static Amount of(int amount, Currency currency) { return new Amount(amount, currency); } }

Slide 335

Slide 335 text

04.03.25 //// Seite 662 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public class Amount { private final int _amount; private final Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } @Override public boolean equals(Object other) { return _amount == ((Amount) other)._amount && _currency.equals(((Amount) other)._currency); } }

Slide 336

Slide 336 text

04.03.25 //// Seite 663 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public class Amount { private final int _amount; private final Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } @Override public boolean equals(Object other) { return _amount == ((Amount) other)._amount && _currency.equals(((Amount) other)._currency); } // hashCode() }

Slide 337

Slide 337 text

04.03.25 //// Seite 664 WPS – Workplace Solutions AN AMOUNT TYPE—JAVA 14 AND HIGHER @ValueObject public record Amount(int amount, Currency currency);

Slide 338

Slide 338 text

04.03.25 //// Seite 665 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public record Amount(int amount, Currency currency) { public Amount add(Amount otherAmount) { return Amount.of(amount + otherAmount.amount, currency); } } The new type has domain behavior

Slide 339

Slide 339 text

04.03.25 //// Seite 666 WPS – Workplace Solutions AN AMOUNT TYPE @ValueObject public record Amount(int amount, Currency currency) { public Amount add(Amount otherAmount) { assert hasSameCurrency(otherAmount); return Amount.of(amount + otherAmount.amount, currency); } public boolean hasSameCurrency(Amount otherAmount) { return otherAmount.currency == currency; } } ... and contracts ensure the correct currency

Slide 340

Slide 340 text

04.03.25 //// Seite 670 WPS – Workplace Solutions A BANK ACCOUNT—FOURTH VERSION @Entity public class Account { private Amount _balance; public Amount balance() { return _balance; } public void deposit(Amount amount) { _balance = _balance.add(amount); } public void withdraw(Amount amount) { assert amount.isLessOrEqual(balance()); _balance = _balance.subtract(amount); } } Now we can use the amount type

Slide 341

Slide 341 text

04.03.25 //// Seite 671 WPS – Workplace Solutions A BANK ACCOUNT—FOURTH VERSION @Entity public class Account { private Amount _balance; public Amount balance() { return _balance; } public void deposit(Amount amount) { _balance = _balance.add(amount); } public void withdraw(Amount amount) { assert amount.hasSameCurrency(balance()); assert amount.isLessOrEqual(balance()); _balance = _balance.subtract(amount); } } ... and define new contracts

Slide 342

Slide 342 text

04.03.25 //// Seite 672 WPS – Workplace Solutions A BANK ACCOUNT—EVENT SOURCED @Entity public class Account { private List _transactions; public Amount balance() { // sum up _transactions } public void deposit(Amount amount) { _transactions.append(new Deposition(amount)); } public void withdraw(Amount amount) { assert amount.hasSameCurrency(balance()); assert amount.isLessOrEqual(balance()); _transactions.append(new Withdrawal(amount)); } } History instead of current status

Slide 343

Slide 343 text

04.03.25 //// Seite 675 WPS – Workplace Solutions IDENTITY OF ENTITIES § In Java, every object has an identity § Namely its reference. § It’s a technical identity. § An entity has a identity from a domain perspective § Different technical objects can represent the same entity § In different processes: e.g. on the client / on the server § When they are stored and later read from the database. § The identity can be implemented in two ways: § explicitly (e.g. IBAN) by using a unique key the user is aware of § implicitly (e.g. UUID / GUID) by using a technical key hidden from the user ?

Slide 344

Slide 344 text

04.03.25 //// Seite 676 WPS – Workplace Solutions A BANK ACCOUNT—WITH EXPLICIT IDENTITY @Entity public class Account { @Identity private final IBAN _iban; public Account(IBAN iban) { _iban = iban; } @Override public boolean equals(Object other) { return _iban.equals(((Account)other)._iban); } // ... } The identity is immutable The key is of course a value object The implementation of equals() is based on the identity

Slide 345

Slide 345 text

04.03.25 //// Seite 677 WPS – Workplace Solutions HOW CAN A NEW IDENTITY BE CREATED? § Database § Pro: Central § Can sometimes be created “lazily” § A system-wide value type factory § Domain-specific keys known to the user § Often implemented by the repository of a corresponding aggregate type the key is used for § A UUID / GUID generator § Pro: can be generated independently on any server or client § Con: String in a special format

Slide 346

Slide 346 text

04.03.25 //// Seite 678 WPS – Workplace Solutions BANK TRANSFER—BY DOMAIN SERVICE @Service public class CreditTransferService { public void transfer(Account source, Account destination, Amount amount) { source.withdraw(amount); destination.deposit(amount); } } No fields à stateless

Slide 347

Slide 347 text

EXERCISE: MOBPROGRAMMING @ THE CINEMA

Slide 348

Slide 348 text

04.03.25 //// Seite 681 WPS – Workplace Solutions EVERY BOUNDED CONTEXT HAS ITS OWN GLOSSARY—REVISITED DEPTH DEPTH AT A SPECIFIC GEO POSITION CONSIDERING THE CURRENT TIDAL LEVEL DEPTH DEPTH BELOW SEA LEVEL MEASURED BY ECHO SOUNDER MANEUVER PLANNING DEPTH MEASUREMENT

Slide 349

Slide 349 text

04.03.25 //// Seite 682 WPS – Workplace Solutions EVERY BOUNDED CONTEXT HAS ITS OWN IMPLEMENTATION public struct Depth { public Depth( int depthBelowSeaLevel, int tideLevel) { // ... } } MANEUVER PLANNING DEPTH MEASUREMENT public class Depth { public Depth( int centimeter, LocalDate soundingDate) { // ... } }

Slide 350

Slide 350 text

WPS – Workplace Solutions #dddkonkret www.wps.de IMPLEMENTING THE BUILDING BLOCKS IN C# Domain-Driven Design concrete

Slide 351

Slide 351 text

04.03.25 //// Seite 684 WPS – Workplace Solutions

Slide 352

Slide 352 text

04.03.25 //// Seite 685 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT public class Account { }

Slide 353

Slide 353 text

04.03.25 //// Seite 686 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT using NMolecules.DDD; [Entity] public class Account { }

Slide 354

Slide 354 text

04.03.25 //// Seite 687 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT [Entity] public class Account { public int Balance { get; set; } } ✘ Bad: The account balance can be set to any value

Slide 355

Slide 355 text

04.03.25 //// Seite 688 WPS – Workplace Solutions A BANK ACCOUNT—SECOND VERSION [Entity] public class Account { public int Balance { get; private set; } public void Deposit(int amount) { Balance += amount; } public void Withdraw(int amount) { Balance -= amount; } } Better: Operations with domain-specific behavior and names

Slide 356

Slide 356 text

04.03.25 //// Seite 689 WPS – Workplace Solutions A BANK ACCOUNT—THIRD VERSION [Entity] public class Account { public int Balance { get; private set; } public void Deposit(int amount) { Balance += amount; } public void Withdraw(int amount) { if (amount > balance()) { throw new ArgumentException("Amount too big"); } Balance -= amount; } Even better: Preconditions can be checked

Slide 357

Slide 357 text

04.03.25 //// Seite 691 WPS – Workplace Solutions DESIGN BY CONTRACT Foto: Urheber Fuchsias/Bertrand Meyer/Wikipedia/CC BY-SA 4.0

Slide 358

Slide 358 text

04.03.25 //// Seite 694 WPS – Workplace Solutions A BANK ACCOUNT—DESIGN BY CONTRACT USING “ASSERT” using static System.Diagnostics.Debug; [Entity] public class Account { // ... public void Withdraw(int amount) { Assert(amount <= balance()); Balance -= amount; } } Assertion using Debug.Assert

Slide 359

Slide 359 text

04.03.25 //// Seite 695 WPS – Workplace Solutions GREAT, BUT… using static System.Diagnostics.Debug; [Entity] public class Account { // ... public void Withdraw(int amount) { Assert(amount <= balance()); Balance -= amount; } } Can I withdraw a negative amount? In EUR or GBP or…?

Slide 360

Slide 360 text

04.03.25 //// Seite 697 WPS – Workplace Solutions AN AMOUNT TYPE public class Amount { }

Slide 361

Slide 361 text

04.03.25 //// Seite 698 WPS – Workplace Solutions AN AMOUNT TYPE using NMolecules.DDD; [ValueObject] public class Amount { }

Slide 362

Slide 362 text

04.03.25 //// Seite 699 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private int _amount; private Currency _currency; }

Slide 363

Slide 363 text

04.03.25 //// Seite 700 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; }

Slide 364

Slide 364 text

04.03.25 //// Seite 701 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } }

Slide 365

Slide 365 text

04.03.25 //// Seite 702 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; private Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } public static Amount Of(int amount, Currency currency) { return new Amount(amount, currency); } }

Slide 366

Slide 366 text

04.03.25 //// Seite 703 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; // ... public override bool Equals(object other) { return other is Amount && _amount == ((Amount) other)._amount && _currency.Equals(((Amount) other)._currency); } }

Slide 367

Slide 367 text

04.03.25 //// Seite 704 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; // ... public override bool Equals(object other) => other is Amount && _amount == ((Amount) other)._amount && _currency.Equals(((Amount) other)._currency); }

Slide 368

Slide 368 text

04.03.25 //// Seite 705 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; // ... public override bool Equals(object other) => other is Amount && _amount == ((Amount) other)._amount && _currency.Equals(((Amount) other)._currency); // GetHashCode() }

Slide 369

Slide 369 text

04.03.25 //// Seite 706 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; // ... public static bool operator ==(Amount a, Amount b) => a.Equals(b); }

Slide 370

Slide 370 text

04.03.25 //// Seite 707 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public class Amount { private readonly int _amount; private readonly Currency _currency; // ... public static bool operator ==(Amount a, Amount b) => a.Equals(b); public static bool operator !=(Amount a, Amount b) => !a.Equals(b); }

Slide 371

Slide 371 text

No content

Slide 372

Slide 372 text

04.03.25 //// Seite 709 WPS – Workplace Solutions 3 CLASSES DEFINE REFERENCE TYPES

Slide 373

Slide 373 text

04.03.25 //// Seite 710 WPS – Workplace Solutions 3 STRUCTS DEFINE VALUE TYPES

Slide 374

Slide 374 text

04.03.25 //// Seite 711 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public struct Amount { private readonly int _amount; private readonly Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } }

Slide 375

Slide 375 text

04.03.25 //// Seite 712 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public struct Amount { private readonly int _amount; private readonly Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } // Equals() does not have to be overridden }

Slide 376

Slide 376 text

04.03.25 //// Seite 713 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public struct Amount { private readonly int _amount; private readonly Currency _currency; public Amount(int amount, Currency currency) { _amount = amount; _currency = currency; } // Equals() does not have to be overridden // but the operators have to be overridden }

Slide 377

Slide 377 text

@hschwentner equals() ! == "

Slide 378

Slide 378 text

04.03.25 //// Seite 715 WPS – Workplace Solutions AN AMOUNT TYPE—C# 9 AND HIGHER [ValueObject] public record Amount(int amount, Currency currency);

Slide 379

Slide 379 text

04.03.25 //// Seite 716 WPS – Workplace Solutions AN AMOUNT TYPE—C# 9 AND HIGHER [ValueObject] public record Amount(int amount, Currency currency); // automatically readonly // Equals(), GetHashCode(), ToString(), operators // do not have to be overloaded and work as expected

Slide 380

Slide 380 text

04.03.25 //// Seite 717 WPS – Workplace Solutions AN AMOUNT TYPE—C# 9 AND HIGHER [ValueObject] public record struct Amount(int amount, Currency currency);

Slide 381

Slide 381 text

04.03.25 //// Seite 718 WPS – Workplace Solutions AN AMOUNT TYPE—C# 10 AND HIGHER [ValueObject] public readonly record struct Amount(int amount, Currency currency);

Slide 382

Slide 382 text

04.03.25 //// Seite 719 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public readonly record struct Amount(int amount, Currency currency) { public Amount Add(Amount otherAmount) { return Amount.of(this.amount + otherAmount.amount, this.currency); } } The new value object type behaves correctly

Slide 383

Slide 383 text

04.03.25 //// Seite 720 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public readonly record struct Amount(int amount, Currency currency) { public Amount Add(Amount otherAmount) { Assert(HasSameCurrency(otherAmount)); return Amount.of(this.amount + otherAmount.amount, this.currency); } public boolean HasSameCurrency(Amount otherAmount) => otherAmount.currency == this.currency; } ... and contracts ensure the correct currency

Slide 384

Slide 384 text

04.03.25 //// Seite 721 WPS – Workplace Solutions AN AMOUNT TYPE [ValueObject] public readonly record struct Amount(int amount, Currency currency) { public Amount operator +(Amount otherAmount) { Assert(HasSameCurrency(otherAmount)); return Amount.Of(this.amount + otherAmount.amount, this.currency); } public boolean HasSameCurrency(Amount otherAmount) => otherAmount.currency == this.currency; }

Slide 385

Slide 385 text

04.03.25 //// Seite 722 WPS – Workplace Solutions A BANK ACCOUNT—FOURTH VERSION [Entity] public class Account { public Amount Balance { get; private set; } public void Deposit(Amount amount) { Balance += amount; } public void Withdraw(Amount amount) { Assert(amount <= Balance); Balance -= amount; } } Now we can use the amount type

Slide 386

Slide 386 text

04.03.25 //// Seite 723 WPS – Workplace Solutions A BANK ACCOUNT—FOURTH VERSION [Entity] public class Account { public Amount Balance { get; private set; } public void Deposit(Amount amount) { Balance += amount; } public void Withdraw(Amount amount) { Assert(amount.HasSameCurrencyAs(Balance); Assert(amount <= Balance); Balance -= amount; } } ... and define new contracts

Slide 387

Slide 387 text

04.03.25 //// Seite 724 WPS – Workplace Solutions A BANK ACCOUNT—EVENT SOURCED [Entity] public class Account { private IList _transactions; public Amount Balance { get { // sum up _transactions } } public void Deposit(Amount amount) { _transactions.Add(new Deposition(amount)); } public void Withdraw(Amount amount) { Assert(amount.HasSameCurrencyAs(Balance); Assert(amount <= Balance); _transactions.Add(new Withdrawal(amount)); } History instead of current status

Slide 388

Slide 388 text

04.03.25 //// Seite 727 WPS – Workplace Solutions IDENTITY OF ENTITIES § In Java, every object has an identity § Namely its reference. § It's a technical identity. § An entity has a identity from a domain perspective § Different technical objects can represent the same entity § In different processes: e.g. on the client / on the server § When they are stored and later read from the database. § The identity can be implemented in two ways: § explicitly (e.g. IBAN) by using a unique key the user is aware of § implicitly (e.g. UUID / GUID) by using a technical key hidden from the user ?

Slide 389

Slide 389 text

04.03.25 //// Seite 728 WPS – Workplace Solutions A BANK ACCOUNT—WITH EXPLICIT IDENTITY [Entity] public class Account { [Identity] private readonly IBAN _iban; public Account(IBAN iban) { _iban = iban; } public override bool Equals(Object other) { return _iban.Equals(((Account)other)._iban); } // ... } The identity is immutable The identity is a value object The implementation of Equals() is based on the identity

Slide 390

Slide 390 text

04.03.25 //// Seite 729 WPS – Workplace Solutions HOW CAN A NEW IDENTITY BE CREATED? § Database § Pro: Central § Can sometimes be created “lazily” § A system-wide value type factory § Domain-specific keys known to the user § Often implemented by the repository of a corresponding aggregate type the key is used for § A UUID / GUID generator § Pro: can be generated independently on any server or client § Con: String in a special format

Slide 391

Slide 391 text

04.03.25 //// Seite 730 WPS – Workplace Solutions BANK TRANSFER—BY DOMAIN SERVICE [Service] public class CreditTransferService { public void Transfer(Account source, Account destination, Amount amount) { source.Withdraw(amount); destination.Deposit(amount); } } No fields à stateless

Slide 392

Slide 392 text

EXERCISE: MOBPROGRAMMING @ THE CINEMA

Slide 393

Slide 393 text

04.03.25 //// Seite 733 WPS – Workplace Solutions EVERY BOUNDED CONTEXT HAS ITS OWN GLOSSARY—REVISITED DEPTH DEPTH AT A SPECIFIC GEO POSITION CONSIDERING THE CURRENT TIDAL LEVEL DEPTH DEPTH BELOW SEA LEVEL MEASURED BY ECHO SOUNDER MANEUVER PLANNING DEPTH MEASUREMENT

Slide 394

Slide 394 text

04.03.25 //// Seite 734 WPS – Workplace Solutions EVERY BOUNDED CONTEXT HAS ITS OWN IMPLEMENTATION public struct Depth { public Depth( int depthBelowSeaLevel, int tideLevel) { // ... } } MANEUVER PLANNING DEPTH MEASUREMENT public class Depth { public Depth( int centimeter, LocalDate soundingDate) { // ... } }

Slide 395

Slide 395 text

WPS – Workplace Solutions #dddkonkret www.wps.de IMPLEMENTING THE BUILDING BLOCKS IN PHP Domain-Driven Design concrete

Slide 396

Slide 396 text

04.03.25 //// Seite 736 WPS – Workplace Solutions

Slide 397

Slide 397 text

04.03.25 //// Seite 737 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT class Account { }

Slide 398

Slide 398 text

04.03.25 //// Seite 738 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT use PHPMolecules\DDD\Attribute\Entity; #[Entity] class Account { }

Slide 399

Slide 399 text

04.03.25 //// Seite 739 WPS – Workplace Solutions A BANK ACCOUNT—FIRST DRAFT #[Entity] class Account { private int $balance; public function getBalance(): int { return $this->balance; } public function setBalance(int $balance): void { $this->balance = $balance; } } ✘ Bad: The account balance can be set to any value

Slide 400

Slide 400 text

04.03.25 //// Seite 740 WPS – Workplace Solutions A BANK ACCOUNT—SECOND VERSION #[Entity] class Account { private int $balance; public funtion balance(): int { return $this->balance; } public function deposit(int amount): void { $this->balance += amount; } public function withdraw(int amount): void { $this->balance -= amount; } } Better: Operations with domain-specific behavior and names

Slide 401

Slide 401 text

04.03.25 //// Seite 741 WPS – Workplace Solutions A BANK ACCOUNT—THIRD VERSION Even better: Preconditions can be checked #[Entity] class Account { private int $balance; public funtion balance(): int { return $this->balance; } public function deposit(int amount): void { $this->balance += amount; } public function withdraw(int amount): void { assert(amount <= $this->balance()); $this->balance -= amount; }

Slide 402

Slide 402 text

04.03.25 //// Seite 743 WPS – Workplace Solutions DESIGN BY CONTRACT Foto: Urheber Fuchsias/Bertrand Meyer/Wikipedia/CC BY-SA 4.0

Slide 403

Slide 403 text

04.03.25 //// Seite 744 WPS – Workplace Solutions DESIGN BY CONTRACT IN PHP § https://github.com/php-deal § http://www.terminally-incoherent.com/blog/2008/06/05/design-by-contract-in-php-with-assertions/

Slide 404

Slide 404 text

04.03.25 //// Seite 745 WPS – Workplace Solutions GREAT, BUT… #[Entity] class Account { // ... public function withdraw(int $amount): void { assert($amount <= $this->balance()); $this->balance -= $amount; } } Can I withdraw a negative amount? In EUR or GBP or…?

Slide 405

Slide 405 text

04.03.25 //// Seite 747 WPS – Workplace Solutions AN AMOUNT TYPE class Amount { }

Slide 406

Slide 406 text

04.03.25 //// Seite 748 WPS – Workplace Solutions AN AMOUNT TYPE use PHPMolecules\DDD\Attribute\ValueObject; #[ValueObject] class Amount { }

Slide 407

Slide 407 text

04.03.25 //// Seite 749 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] class Amount { private int $amount; private Currency $currency; }

Slide 408

Slide 408 text

04.03.25 //// Seite 750 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] class Amount { private readonly int $amount; private readonly Currency $currency; }

Slide 409

Slide 409 text

04.03.25 //// Seite 752 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] class Amount { private readonly int $amount; private readonly Currency $currency; public function __construct(int $amount, Currency $currency) { $this->amount = $amount; $this->currency = $currency; } }

Slide 410

Slide 410 text

04.03.25 //// Seite 753 WPS – Workplace Solutions AN AMOUNT TYPE—PHP 8.1 AND HIGHER #[ValueObject] class Amount { public function __construct( private readonly int $amount, private readonly Currency $currency ) {} }

Slide 411

Slide 411 text

04.03.25 //// Seite 754 WPS – Workplace Solutions AN AMOUNT TYPE—PHP 8.2 AND HIGHER #[ValueObject] readonly class Amount { public function __construct( private int $amount; private Currency $currency; ) {} }

Slide 412

Slide 412 text

04.03.25 //// Seite 755 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] readonly class Amount { private function __construct( private int $amount, private Currency $currency ) {} public static function of(int $amount, Currency $currency): Amount { return new Amount($amount, $currency); } }

Slide 413

Slide 413 text

04.03.25 //// Seite 756 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] readonly class Amount { public function __construct( private int $amount; private Currency $currency; ) {} public function equals(Amount $other): bool { return $this->amount === $other->amount && $this->currency->equals($other->currency); } }

Slide 414

Slide 414 text

04.03.25 //// Seite 759 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] readonly class Amount { public function __construct( private int $amount, private Currency $currency ) {} public function add(Amount $otherAmount): Amount { return Amount.of($this->amount + $otherAmount->amount, $this->currency); } } The new value object type behaves correctly

Slide 415

Slide 415 text

04.03.25 //// Seite 760 WPS – Workplace Solutions AN AMOUNT TYPE #[ValueObject] readonly class Amount { public function __construct( private int $amount, private Currency $currency ) {} public function add(Amount $otherAmount): Amount { assert($this->hasSameCurrencyAs($otherAmount)); return Amount.of($this->amount + $otherAmount->amount, $this->currency); } public function hasSameCurrencyAs(Amount $otherAmount): bool { return $this->currency === $otherAmount->currency; } } ... and contracts ensure the correct currency

Slide 416

Slide 416 text

04.03.25 //// Seite 761 WPS – Workplace Solutions A BANK ACCOUNT—FOURTH VERSION Now we can use the amount type #[Entity] class Account { private Amount $balance; public function balance(): Amount { return $this->balance; } public function deposit(Amount $amount): void { $this->balance = $this->balance->add($amount); } public function withdraw(Amount $amount): void { assert($amount.isLessOrEqual($this->balance()); $this->balance = $this->balance->subtract($amount); }

Slide 417

Slide 417 text

04.03.25 //// Seite 762 WPS – Workplace Solutions #[Entity] class Account { private Amount $balance; public function balance(): Amount { return $this->balance; } public function deposit(Amount $amount): void { $this->balance = $this->balance->add($amount); } public function withdraw(Amount $amount): void { assert $amount.hasSameCurrency($this->balance()); assert($amount.isLessOrEqual($this->balance()); $this->balance = $this->balance->subtract($amount); A BANK ACCOUNT—FOURTH VERSION ... and define new contracts

Slide 418

Slide 418 text

04.03.25 //// Seite 763 WPS – Workplace Solutions A BANK ACCOUNT—EVENT SOURCED class Account { /** @var FinancialTransaction[] */ private $transactions; public function balance(): Amount { // sum up $transactions } public function deposit(Amount $amount): void { $this->transactions[] = new Deposition($amount); } public function withdraw(Amount $amount): void { assert($amount->hasSameCurrencyAs(balance()); assert($amount->isLessOrEqualTo(balance()); $this->transactions[] = new Withdrawal(amount); History instead of current status

Slide 419

Slide 419 text

04.03.25 //// Seite 766 WPS – Workplace Solutions IDENTITY OF ENTITIES § In Java, every object has an identity § Namely its reference. § It's a technical identity. § An entity has a identity from a domain perspective § Different technical objects can represent the same entity § In different processes: e.g. on the client / on the server § When they are stored and later read from the database. § The identity can be implemented in two ways: § explicitly (e.g. IBAN) by using a unique key the user is aware of § implicitly (e.g. UUID / GUID) by using a technical key hidden from the user ?

Slide 420

Slide 420 text

04.03.25 //// Seite 767 WPS – Workplace Solutions A BANK ACCOUNT—USING A UNIQUE KEY #[Entity] public class Account { #[Identity] private readonly IBAN $iban; public __construct(IBAN $iban) { $this->iban = $iban; } public function equals(Account $other): bool { return $this->iban.equals($other->iban); } // ... } The identity is immutable The key is of course a value object The implementation of equals () is based on the unique key

Slide 421

Slide 421 text

04.03.25 //// Seite 768 WPS – Workplace Solutions HOW CAN A NEW UNIQUE KEY BE CREATED? § Database § Pro: Central § Can sometimes be created “lazily” § A system-wide value type factory § Domain-specific keys known to the user § Often implemented by the repository of a corresponding aggregate type the key is used for § A UUID / GUID generator § Pro: can be generated independently on any server or client § Con: String in a special format

Slide 422

Slide 422 text

04.03.25 //// Seite 769 WPS – Workplace Solutions BANK TRANSFER—BY DOMAIN SERVICE #[Service] public class CreditTransferService { public function transfer(Account $source, Account $destination, Amount $amount): void { $source->withdraw(amount); $destination->deposit(amount); } } No fields à stateless

Slide 423

Slide 423 text

EXERCISE: MOBPROGRAMMING @ THE CINEMA

Slide 424

Slide 424 text

04.03.25 //// Seite 772 WPS – Workplace Solutions EVERY BOUNDED CONTEXT HAS ITS OWN GLOSSARY—REVISITED DEPTH DEPTH AT A SPECIFIC GEO POSITION CONSIDERING THE CURRENT TIDAL LEVEL DEPTH DEPTH BELOW SEA LEVEL MEASURED BY ECHO SOUNDER MANEUVER- PLANNING SOUNDING SERVICE

Slide 425

Slide 425 text

04.03.25 //// Seite 773 WPS – Workplace Solutions EVERY BOUNDED CONTEXT HAS ITS OWN IMPLEMENTATION public struct Depth { public Depth( int depthBelowSeaLevel, int tideLevel) { // ... } } MANEUVER- PLANNING SOUNDING SERVICE public class Depth { public Depth( int centimeter, LocalDate soundingDate) { // ... } }

Slide 426

Slide 426 text

No content

Slide 427

Slide 427 text

No content

Slide 428

Slide 428 text

@hschwentner What now?

Slide 429

Slide 429 text

Architecture Hamburger Application Domain Infrastructure UI coarse grained Henning Schwentner !

Slide 430

Slide 430 text

Architecture Hamburger fine grained model repository interface controller use case service entity value object view data model repository implementation widget library REST frame- work transaction handling domain library programming language ORM file system access domain event

Slide 431

Slide 431 text

@hschwentner Further topics: Ubiquitous Language Tactical Design (Entity, Value Object, Aggregate, Repository, Service)

Slide 432

Slide 432 text

Workshop Domain-Driven Design konkret wps.de/ddd

Slide 433

Slide 433 text

No content

Slide 434

Slide 434 text

@hschwentner LeasingNinja.io

Slide 435

Slide 435 text

@hschwentner Literature

Slide 436

Slide 436 text

https://hschwentner.io

Slide 437

Slide 437 text

May 6th-9th 2024 Vienna, Austria The Collaborative Modeling Unconference comocamp.org Event Storming User Story Mapping Event Modeling Impact Mapping Domain Storytelling Storystorming Context Mapping Example Mapping etc.

Slide 438

Slide 438 text

No content

Slide 439

Slide 439 text

No content

Slide 440

Slide 440 text

@hschwentner FEEDBACK

Slide 441

Slide 441 text

No content

Slide 442

Slide 442 text

No content

Slide 443

Slide 443 text

@hschwentner Bibliography Brandolini, Alberto. Introducing EventStorming. Self-published, Leanpub. Cockburn, Alistair. “Hexagonal Architecture.” January 4, 2005. https://alistair.cockburn.us/hexagonal-architecture/. Conway, Melvin E. “How Do Committees Invent?” Datamation 14, no. 5 (April 1968): 28–31. Evans, Eric. Domain-Driven Design: Tackling Complexity in the Heart of Software. Boston: Addison-Wesley, 2004. Foote, Brian and Joseph Yoder. “Big Ball of Mud.” PLoP ’97, Monticello, IL, September 1997. Fowler, Martin. Patterns of Enterprise Application Architecture. Boston: Addison- Wesley, 2003. Fowler, Martin. “Strangler Fig Application.” Bliki, June 29, 2004. Hofer, Stefan and Henning Schwentner. Domain Storytelling: a Collaborative, Visual, and Agile Way to Develop Domain-Driven Software. Boston: Addison-Wesley, 2022.

Slide 444

Slide 444 text

No content

Slide 445

Slide 445 text

Henning Schwentner  https://hschwentner.io  in/henningschwentner ✉ [email protected] Kolleg:in gesucht (Deutschlandweit)