Domain Driven Design

DDD, domain, domain expert, modelling, ubiquitous language, building blocks, model and OO, whirlpool, contexts, system map

200

Tomasz Borek, @LAFK pl,

In a nutshell

DDD

Domain Driven Design, a way of creating software that uses a business language everywhere, from requirements gathering, through model, code and tests. Usually done with a domain expert(s), it employs several techniques which are roughly divided into tactical and strategic.

Definition mine.

UML and electrical engineers

or how Eric Evans was struck by an inspiration

Ubiquitous language

  1. ubiquitous == omnipresent

  2. tests, docs, code, issues, manuals

  3. customers, BAs, POs, support, devs, QAs

  4. it’s about unambiguous vocabulary

Domain

  1. domain expert is your guide

  2. business invariants, rules, facts, processes

  3. problem reality

  4. this - you model, distill, isolate and rid of complexity

Contexts, maps, boundaries

  1. map the contexts

  2. context per team is possible

  3. define boundaries

  4. mental and org level

New modelling techniques

  1. context mapping

  2. whirlpool

  3. event storming

Strategic patterns

  1. work within Conway’s Law and bounded contexts

  2. problem separation reflected in teams cooperation

  3. should be clear from a context map

  4. work across boundaries

  5. not every piece of the system is equally important

Tactical patterns

  1. address code organization

  2. work within boundaries

  3. design patterns

  4. so-called building blocks

Testing

  1. frequently employes BDD and variants cause language

  2. TDD, ATDD sure

  3. acceptance used heavily in whirlpool

How DDD affects SDLC phases?

all of them, some more than others, some if we pull other 'symbiotic' techniques

Today’s rules

Tempo - as you wish.
Questions - as we go.
Break - one half-way through.

About Sages

  1. Trainings and advisories for IT professionals

  2. for companies in IT and outside, as long as it’s about software

Sages' mission statement

Company’s mission is to support the process of designing, creating and deploying software in corporations and public institutions, to minimize cost, time and risk associated with these endeavours.
http://www.sages.com.pl/sages
— Sages - o nas

translation mine

About me, when not representing Sages

LAFK pl
LAFK pl wSieci

My jobs include

  1. audits of: code, infra, components, design, systems

  2. performance or security tests and audits

  3. dealing with DBs, OS', networks or security

  4. programming jobs

  5. lectures, talks, workshops, trainings

Questions?

question mark
appears rarely, so don’t wait for it

Next steps

be it books, reading or exercises

Books

who has read…​

books DDD EvansBlueBookCover
books DDD VernonRedBookCover
books RefactoringDBs

Older though good about OO through tests?

books GrowingOOByTests
books microservices

about architecture documentation? Chapter 3 onwards…​

books SEI DocumentingSA

Lighter reading

  1. articles by Bottega

  2. their project, Leaven

  3. most things by authors mentioned earlier or later

Exercises

  1. archi-kata

  2. small modelling exercises

  3. small example in various ways, to see what DDD brings

  4. and in a different order

  5. callisthenics

  6. event storming

  7. whirlpool

People

  1. Eric Evans,

  2. Vaughn Vernon,

  3. Alberto Brandolini, @ziobardo

  4. Piotr Wyczesany,

  5. Sławomir Sobótka,

  6. Łukasz Szydło

Questions?

question mark

Word about modelling

In or out of DDD, along with its ailments

Simplification

  1. Modelling was never meant to "take in all"

  2. We skip parts we don’t need or don’t care about

  3. It’s a simplified image

Complexity

Accidental or Essential

Essential complexity

  1. may be inherent to current problem

  2. may be inherent for problem domain

Accidental complexity

  1. is a result of our actions

  2. organizational structure influences how we code

    1. I can’t wait that long for extra sever so…​

    2. no DBAs, so I’ll solve this in code

    3. usually I’d collect data to create user persona but…​

  3. is a result of choices made (tools, libs, tech-debt…​)

Complexity

  1. should be reduced overall

  2. essential may be hard to do so

  3. accidental therefore should be eliminated all the more

CRC cards

CRC

Class Responsibility Collaborators, modelling technique from XP, which just a bit fails with the responsibility part IMO, at least the way it was defined back when XP emerged

Farming+CRC+Cards

Problems with CRC?

  1. responsibility is not a list of attributes or methods

  2. should not be left empty

  3. holds value as a responsibility means failing to encapsulate

  4. doesn’t scale

Universal Modelling Language

  1. a standard borne from 3 - agreeably! :O

  2. extensible with various diagrams and extensions if needed

Problems with UML?

  1. unwieldy - tools were rather heavyweight

  2. hermetic - explain stereotype to a client

  3. not simple - which diagram to choose from 15 types?

Recently C4

  1. but that’s recent (fairly, 2011/2012 or so IIRC)

  2. doesn’t address Conway’s law

  3. not very pattern-oriented

  4. UML distilled and simplified

  5. lightweight - has its advantages

Old techniques

  1. storytelling

  2. customer interviews

  3. requirement discovery

Chaos reports: user interaction and requirements!

Business - IT

  1. business talks in estimates (commitments)

  2. IT talks in estimates (guesses)

  3. different jargon (may well not understand each other)

5 dysfunctions of a team

Modelling 5Dysfunctions

Conway’s law

organizations which design systems …​ are constrained to produce designs which are copies of the communication structures of these organizations.
Melvin Conway
— Conway's Law

To which DDD says

everything can be addressed, if we speak same language as business does

Structured programming

yeah, before OOA/OOD/OOP even - we did programming then! ;-)

  1. coupling (Larry Constantine, late 1960', Structured Design)

  2. cohesion (Larry Constantine, late 1960', Structured Design)

  3. Connascence (Meilir Page-Jones, 1992, Comparing techniques by means of encapsulation and connascence)

Coupling

Tight / Loose Coupling

degree of procedures' (later also object’s) interwovenness, tells how dependent modules are of each other

Cohesion

High / Low Cohesion

how similar are methods of a given objects / procedure gathered in a given module

coupling sketches cropped MatthewKR
cohesion tapez wordpress

It’s all very well but…​

This actually pushes the problem down to a module.

Connascence

two components are connascent if a change in one would require the other to be modified in order to maintain the overall correctness of the system
Connascence
— Wikipedia

Connascence defined

The ideals of low coupling and high cohesion now generalize beyond structured design and yield a statement that is applicable to object-oriented design (or indeed to any future design paradigm with partitioning, encapsulation and visibility rules):
his paper on connascence
— Meilir Page-Jones
Eliminate any unnecessary connascence and then minimize connascence across encapsulation boundaries by maximizing connascence within encapsulation boundaries.
his paper on connascence
— Meilir Page-Jones

Good design metrics and standards then?

  1. failed (coupling, cohesion)

  2. not marketed enough (connascence - a shame)

  3. were not that great for a larger projects (CRC cards)

  4. were a standard, but a bit scary / unwieldy (it’s you, UML)

We’re pretty much left with storytelling, interviews, reqs discovery etc.

What DDD offers?

  1. tactics & strategy

  2. event storming

  3. whirlpool

  4. context mapping (no, not the UI/UX one, this one’s older)

and new building blocks!

Tactics and strategy?

DDD Modelling

DDD tactical bricks

DDD Building Blocks

Value Objects

  1. Wrappers, Containers - great for refactoring

  2. a design pattern

  3. first step when introducing DDD

    1. take a bunch of primitives reflecting a concept

    2. give them a name / codify as a type

  4. no identity, not unique

VO implementations

  • PhoneNumber or a PostalCode

  • often immutable

  • often in method parameters

Entities

  1. have identity, we compare them using it

  2. our crucial concepts are most likely Entities

  3. similar to EJB or DB entities but POJOs

Aggregates

  1. object graphs and/or groups (of VOs and entities)

  2. untouchable, immutable - outside of it you work on copies

  3. this we use to model our domain

Aggregate root

  1. root of the aggregates serves as point of entry

  2. said root is an entity and contains operations on the aggregate

  3. ensures data correctness and consistency through its operations

  4. keeps system invariants

  5. uses delegation and composition

  6. this is why we have rich domain model

DDD Aggregate

System invariants

  1. if A grows, B decreases

  2. you can’t do X twice in a row

Repositories

  1. realizes persistence

    1. works with infra-objects, like DAO, ORMs code

    2. abstracts away the specifics

    3. encapsulates data access and related logic

  2. nowadays in some cases interchangeable with DAO

  3. a design pattern, that introduces a new layer

Domain Services

for operations that don’t belong to any entity - and hence to no aggregates either

Factories

  1. produce aggregates, ensuring their correctness

  2. codifies creation logic, so usually some construction DPs are involved

  3. increases testability, decreases complexity, extracts creational details

Advanced building bricks

  1. sagas

  2. specifications

  3. policies

  4. services

Not today, but do read about them

Strategic design

DDD StrategicPatterns

Bounded Context then?

Bounded Context

The setting in which a word or a statement appears that determines its meaning

Eric Evans would say: cannot change the meaning

Travelling context map

Draw what you know. Send to next person and ask him to fill something till insert date here. Rinse and repeat.

DDD BoundedContext
DDD BoundedContextRevealed

Name all Bounded Contexts

Bounded contexts should have a name so that you can talk about them.
— Eric Evans

Why "Bounded"?

Separates on multiple levels:

  1. mental - different thinking

  2. architectural - different system invariants or requirements

  3. organizational - different teams, departments, locations

  4. vocabulary - same term has different meaning

  5. code - same object has different fields/methods

Between contexts

  1. Distilling domains

  2. Drawing context map

  3. Identifying contexts otherwise allows seeing their relationships === SP Continuous Integration . Integrate people as you can: co-location, ubiquitous language, share teams special know-hows with others

  4. Requires one manager for all teams

    TIP: SP

    here: strategic pattern

SP Anti-corruption layer, ACL

  1. usually via proxy

  2. translation / protection layer

  3. you shall not pass, you abstraction from another bounded context you

SP Shared kernel

  1. if shared DB - wrong

  2. if shared aspect - all right

  3. partnership between teams needed

SP Separate ways

  1. independent teams, independent software

SP Big Ball of Mud

  1. happens to the best of us

  2. just isolate it and make sure it doesn’t contaminate others

did someone just said "integration deadline"?

SP Conformist

  1. one team must conform to the other

  2. sucks to be on that team if the others are not playing nice

  3. ACL all the things!

SP Customer/Supplier

  1. fairly straightforward relationship

  2. web-services are a fine example

Distilling the domain: core

Core Domain

if you don’t have it, you don’t have a product

Core Domain is something that directly traces to the business strategy, to the organization strategy
Strategic Design
— Eric Evans

Hard to spot without answering "how the org wants to use software to leverage their strategy?"

To distill, ask yourself

why write and NOT buy or outsource?

Generic domain

  1. accounting, ERP - unless you’re in accounting of course

  2. share/like/social integration - unless you sell it

  3. off the shelf, outsource - sure

Supporting domain

  1. accounting, ERP - unless you’re in accounting of course

  2. ranking of a product on Amazon - support

it changes with time, in few years the classification may differ
if you don’t differ on core, support is what makes/breaks the deal

Context mapping

Points

  1. terms change their meanings between contexts, but NOT inside

  2. no leaks - context dictates what you mean when you say "student"

  3. separation of concerns

  4. YAGNI

  5. context map makes the boundaries explicit

Examples how context matters

  1. Census SystemAddress is unique, so an entity

  2. Book Rental - Address is just a part of LibraryUser, so a VO

  3. Student in financial context has a name, surname, index number and an account.

  4. Student in student records has no bank account, but has courses and grades

  5. Account in profiling and in payments

Detailed walkthrough

Whirlpool

Whirlpool

in DDD, whirlpool is an approach to producing software, which offers an iterative process with 3 steps: scenario, model and finally code probe (here loop restarts). Whirlpool focuses on creating and revising a dictionary throughout the entire process.

DDD Model Whirlpool

About

  1. it’s called 'model exploration' technique

  2. it uses storytelling and customer interviews

  3. mistakes are taken into account through iterations

    1. new scenarios should unearth them

    2. new insights yield better questions and vocab

  4. obviously dependent on domain experts available

When the language is missing?

  1. team talks about FakeOrder or TempItem (no relation to business domain)

  2. Scrum Velocity drops, lavaflow kicks in

  3. we start hacking around our too complex model

  4. accidental complexity rises, so does technical debt

How we build the language

  1. expert and us flesh out a story - business processes descriptions

  2. model is built, with state changes

  3. code probe delivers services, class headers - walking skeleton approach

  4. we formalize the scenario through live docs - BDD tests

Formalizing our code-probed scenario

  • BDD and acceptance scenario

  • Given (Expert) - When (Programmer) - Then (Expert)

Event storming

or how to use post-its for everything

Most important slide here!

don’t pull a post-it in any other way than left to right, parallel to glued edge

God forbid bottom-up (physics will punish you if you do)!
this is THE most important slide in your entire life. Epic, isn’t it?

Gather the right people

  1. who has the knowledge

  2. different teams

  3. mesh them together

Steps

there’s more than 4 steps but we don’t have time

Modelling problems and DDD then

  1. silos / Conway’s law within org

  2. business to IT communication

  3. measuring / testing the model

  4. transition from model to code

  5. fishing for facts to model / domain know-how

  6. simplifying the domain

Communication

  1. unambiguous language

  2. ubiquitous language

  3. contexts, bounded

  4. solved

Conway’s law

  1. strategic patterns

  2. context mapping for bounded contexts

  3. solved

good modelling metrics

  1. no communication problems

  2. little / no primitives in code

  3. connascence

  4. solved

testing the model

  1. whirlpool

  2. TDD, BDD, ATDD

  3. testing bounded contexts

    1. in isolation

    2. as black boxes if needed

from model to code

  1. tactical patterns

  2. building blocks

  3. solved

domain complexity

  1. smaller accidental - we model less

  2. essential may be reduced by distilling the domain

  3. building blocks / tactical patterns

  4. isolation with layers / boundaries

  5. solved

fishing for domain knowledge

  1. event storming

  2. whirlpool

  3. old techniques still valid

  4. solved

Questions?

question mark

Which model to choose?

And which dominates in practice?

Anemic model advantages

  • always clear where to put what

  • easy code generation (hundreds of classes - sure)

  • IDE generates get/set pairs for ya

  • tools can work on this code automatically

  • coding follows rules

Anemic model disadvantages

  1. tech-packages screw encapsulation

    1. default was never meant to be public

    2. functional packages mean package access is fine

    3. everything to everything, so why not call what shouldn’t be called?

  2. no behaviours, just state manipulation, domain expresses nothing

    1. changing behaviours is constant, but with state manipulation?

A Java example

package com.agency.recruitment.ta;

/** 
 * Simplified from original
 **/
public class Acquisition {

    // cut
    
    public void close(/*5 params here*/) { (1)
        // null-checks and other defensive mechanism, FF and the like
        AgencySession agencySession = SessionManager.getSession();
        CurrentUser cu = agencySession.getCurrentUserPrincipal().getCurrentUser();
        Candidate candidate = cu.getRecentItems().getVacancy().getCandidate();

        Employee employee = new Employee(); (2)
        employee.setFirstName(candidate.getFirstName());
        employee.setLastName(candidate.getLastName());
        employee.setArchivingPolicy(candidate.getArchivingPolicy()); (3)
        employee.setCurrentRate(candidate.getCurrentRate()); (4)
        employee.setEmploymentType(candidate.getEmploymentType()); (5)
        employee.setPermanentEmployment(candidate.isPermanentEmployment());
        employee.setJobTitle(candidate.getJobTitle()); (6)
        employee.setJobSeniority(candidate.getJobSeniority());
        employee.setDepartment(candidate.getDepartment()); (7)
        employee.setCompany(candidate.getCompany());
        employee.setCountry(candidate.getCountry());
        employee.setCity(candidate.getCity());
        boolean wasClosed = cu.getRecentItems().getVacancy().tryClosing();  (8)
        if (!wasClosed) { (9)
            // log, throw
        } 
        // method continues
    }

1. get the candidate

    public void close(/*5 params here*/) {
        // null-checks and other defensive mechanism, FF and the like
        AgencySession agencySession = SessionManager.getSession();
        CurrentUser cu = agencySession.getCurrentUserPrincipal().getCurrentUser();
        Candidate candidate = cu.getRecentItems().getVacancy().getCandidate();
  1. returns void,

  2. input has no candidates

  3. classic trains, to get to the candidate

2. optional setters?

  1. not here, not all, but some

  2. slight variations in their calls? sure

  3. parameterless c-tor call

  4. little subclassing, so EmployeeType set regardless of isPermanent

3. domain problems or not?

  1. seniority sometimes would be in the job title

  2. location wasn’t conceptualized, so we would set:

    1. country and region and city and postal-code sometimes

    2. company and department

  3. rate was virtually always displayed in local rates

  4. some customers had distributed departments, some had them 'uni-located'

4. what do those mean?

vacancy, job offer, applicant, candidate, posting, advertisement, position

Alternative?

Employee newHire = candidate.hire();

  1. same logic every time, codified

  2. on a Candidate, not a side-effect when closing Acquisition

  3. business language maps to object.method() - ubiquitous language

  4. easier to grasp and learn the relevant domain process

Anemic2Rich in steps

  1. identify concepts and wrap them

  2. extract classes, note variants and deal with them

  3. connected objects should stay connected - use aggregates

  4. transform the aggregate A into aggregate B with a service if needed

  5. stay within boundaries of your current context

  6. go across boundaries according to proper procedures

Id the concepts - location

        employee.setCountry(candidate.getCountry());
        employee.setCity(candidate.getCity());
package com.agency.recruitment.ta;

import net.jcip.annotations;
/** 
 * Wraps around location-related items, to speed up search and codify related operations.
 * Verifies if location is same as another
 **/
@Immutable
class Location {

    // city, country, coordinates

    boolean isSame(Location other) { (1)
        return Objects.equals(city, other.city) && Objects.equals(country,other.country);
    }

    boolean isWithinRadius(int kms, Location from) { (2)
        return compareByCoordinates(kms, from);
    }
}
1different names for same location - no longer a problem if this would be done cleverly
2there are cases when candidates look for a job in a given radius

Id the concepts - rate

        employee.setCurrentRate(candidate.getCurrentRate());
package com.agency.recruitment.ta;

import net.jcip.annotations;

/** 
 * Codified rates, along with their currencies.
 **/
@Immutable
class Rate {

    BigDecimal amount; (1)
    Currency currency; (2)

    (3)
}
1cause various dinars (and few others) don’t have 1:100 step
2and now currency is unchangeable and may be immutable (like enum)
3possible to add currency conversions, raises, spreads, etc., just return a new Rate object, changed appropriately

DDD advantages

  1. ubiquitous language

    1. prose in the code

    2. business talks, dev maps to object.method call

  2. rich domain model - has behaviours

    1. easy reading / changing

    2. harder for lazyness, fear or difficulties to make one reluctant to change the code

DDD drawbacks

  1. so strong as your domain expert’s knowledge - more of a limitation

  2. most people stop at tactical level

What to choose?

Team skills and domain expert know-how are primary factors.

Questions?

question mark

SDLC

SDLC

Software Development Life Cycle

  1. idea → requirements

  2. design (modelling)

  3. coding → testing

  4. deployment

  5. maintenance

  6. sunsetting the product

And DDD?

All of them if we want. Most of them if done somewhat right.

Symbiotic or friendly technologies and solutions may increase the effect.

Friendly to DDD

  1. layered architecture

  2. hexagon architecture, or ports and adapters

  3. well-done OOP (encapsulation, no/little state-sharing)

  4. BDD, ABDD, ATDD and relevant libraries

  5. microservices if done right (as well as our modelling)

  6. strong domain experts

DDD actually is tech-agnostic.

Requirements phase and DDD

  1. domain expert

  2. distilling domain (core, support…​)

  3. whirlpool, event storming

  4. ubiquitous, unabiguous language

Modelling phase and DDD

  1. whirlpool

  2. event storming

  3. language

  4. domain focus

  5. rich domain model

Coding…​

  1. building blocks

  2. patterns (tactical and design)

Maintenance…​

  1. clear code through building blocks

  2. reflects domain so strong and protected invariants

  3. domain truths usually coded down

  4. bounded contexts and ACLs

  5. strategic patterns help form cooperation rules between departments

Testing…​

  1. acceptance tests

  2. behaviour-driven tests

  3. 'normal', unit- and or system tests

  4. easier integration tests - bounded contexts

xDD

DDD TDD BDD intersection

Deploy…​

  1. may be easier if contexts separated

  2. with good µservices where 1 µserv. means 1 bounded context - easy

  3. with distributed monolith usually somewhat harder

  4. least gain per se

Questions?

question mark

Summarizing

  1. Helps through all the phases of SDLC

  2. Strategic, tactical, language, model

  3. Event storming, whirlpool, context map

New way if thinking

  1. technology-agnostic

  2. domain-centric

  3. one language to rule them all

Word cloud

if existing project - get a word cloud from code to see concepts and try finding your ubiquitous language terms that way

Modelling metrics

  1. Callisthenics

  2. Coupling, cohesion - meh

  3. Connascence - better

  4. Function-centric packages, not technical ones

  5. Code is a prose

  6. Good OOP

Contexts

  1. have names

  2. keep meaning true

  3. are multi-level: org, mental, vocab…​

  4. minimum aggregate is one entity

  5. minimum context is one aggregate…​

DDD tactics

  1. VO and Entities together create Aggregates

  2. Factories encapsulate creation logic

  3. Repositories abstract away data persistence access layer

  4. There’s more

DDD strategies

  1. org structure will influence your contexts

  2. ubiquitous, unabimguous language

  3. between contexts: relationships

  4. Anti-Corruption Layer protects meaning from leaking or changing

  5. Continuous Integration supports heavy and non-stop cooperation

  6. Customer - Supplier is BAU

  7. Conformist is when it goes to hell (bad Supplier)

  8. There’s more

Domains

  1. core, support, generic

  2. invest in core, buy generic

  3. change in time

  4. distilling may cut complexity

Modelling techniques

  1. CRC, UML, C4

  2. storytelling, requirements discovery, customer interview

  3. whirlpool, context map, event storming

Context map

  1. can be found after several aggregates are drawn

  2. can be seen after event streams in event storming are done

  3. makes concepts visible, can help with domain distilling

Wandering?

  1. draw what you will

  2. pass to next person so he can do the same

  3. collect or wait once it gets back

Archi-kata

  1. gather reqs for target architecture

  2. group people, reserve 3 hours

  3. each group designs and presents, questions are a must

You can also hire Tomek to facilitate

Coding DDD

  1. start with VOs, identify - name - codify

  2. entites next

  3. aggregates are key

  4. 1 entity == min aggregates

  5. 1 aggregate == min bounded context

  6. then services and more advanced tactics

Better?

  1. start with modelling, it’s number 1

  2. context map - distill domains

  3. event storm - find aggregates, choke points

  4. whirlpool - steady influx of terms to language

  5. ubiquitous and unabigous language

  6. perhaps hexagon, it won’t auto-evolve

  7. test with TDD/ATDD/BDD to prove your model

Questions?

question mark