God forbid bottom-up (physics will punish you if you do)!
DDD, domain, domain expert, modelling, ubiquitous language, building blocks, model and OO, whirlpool, contexts, system map
Tomasz Borek, @LAFK pl,
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.
or how Eric Evans was struck by an inspiration
ubiquitous == omnipresent
tests, docs, code, issues, manuals
customers, BAs, POs, support, devs, QAs
it’s about unambiguous vocabulary
domain expert is your guide
business invariants, rules, facts, processes
problem reality
this - you model, distill, isolate and rid of complexity
map the contexts
context per team is possible
define boundaries
mental and org level
context mapping
whirlpool
event storming
work within Conway’s Law and bounded contexts
problem separation reflected in teams cooperation
should be clear from a context map
work across boundaries
not every piece of the system is equally important
address code organization
work within boundaries
design patterns
so-called building blocks
frequently employes BDD and variants cause language
TDD, ATDD sure
acceptance used heavily in whirlpool
all of them, some more than others, some if we pull other 'symbiotic' techniques
Tempo - as you wish.
Questions - as we go.
Break - one half-way through.
Trainings and advisories for IT professionals
for companies in IT and outside, as long as it’s about software
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.
translation mine
audits of: code, infra, components, design, systems
performance or security tests and audits
dealing with DBs, OS', networks or security
programming jobs
lectures, talks, workshops, trainings
appears rarely, so don’t wait for it |
be it books, reading or exercises
who has read…
Older though good about OO through tests?
about architecture documentation? Chapter 3 onwards…
articles by Bottega
their project, Leaven
most things by authors mentioned earlier or later
archi-kata
small modelling exercises
small example in various ways, to see what DDD brings
and in a different order
callisthenics
event storming
whirlpool
Eric Evans,
Vaughn Vernon,
Alberto Brandolini, @ziobardo
Piotr Wyczesany,
Sławomir Sobótka,
Łukasz Szydło
In or out of DDD, along with its ailments
Modelling was never meant to "take in all"
We skip parts we don’t need or don’t care about
It’s a simplified image
Accidental or Essential
may be inherent to current problem
may be inherent for problem domain
is a result of our actions
organizational structure influences how we code
I can’t wait that long for extra sever so…
no DBAs, so I’ll solve this in code
usually I’d collect data to create user persona but…
is a result of choices made (tools, libs, tech-debt…)
should be reduced overall
essential may be hard to do so
accidental therefore should be eliminated all the more
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
responsibility is not a list of attributes or methods
should not be left empty
holds value as a responsibility means failing to encapsulate
doesn’t scale
a standard borne from 3 - agreeably! :O
extensible with various diagrams and extensions if needed
unwieldy - tools were rather heavyweight
hermetic - explain stereotype to a client
not simple - which diagram to choose from 15 types?
but that’s recent (fairly, 2011/2012 or so IIRC)
doesn’t address Conway’s law
not very pattern-oriented
UML distilled and simplified
lightweight - has its advantages
storytelling
customer interviews
requirement discovery
Chaos reports: user interaction and requirements! |
business talks in estimates (commitments)
IT talks in estimates (guesses)
different jargon (may well not understand each other)
organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.
everything can be addressed, if we speak same language as business does
yeah, before OOA/OOD/OOP even - we did programming then! ;-)
coupling (Larry Constantine, late 1960', Structured Design)
cohesion (Larry Constantine, late 1960', Structured Design)
Connascence (Meilir Page-Jones, 1992, Comparing techniques by means of encapsulation and connascence)
degree of procedures' (later also object’s) interwovenness, tells how dependent modules are of each other
how similar are methods of a given objects / procedure gathered in a given module
This actually pushes the problem down to a module.
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
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):
Eliminate any unnecessary connascence and then minimize connascence across encapsulation boundaries by maximizing connascence within encapsulation boundaries.
failed (coupling, cohesion)
not marketed enough (connascence - a shame)
were not that great for a larger projects (CRC cards)
were a standard, but a bit scary / unwieldy (it’s you, UML)
We’re pretty much left with storytelling, interviews, reqs discovery etc.
tactics & strategy
event storming
whirlpool
context mapping (no, not the UI/UX one, this one’s older)
and new building blocks!
Wrappers, Containers - great for refactoring
a design pattern
first step when introducing DDD
take a bunch of primitives reflecting a concept
give them a name / codify as a type
no identity, not unique
PhoneNumber
or a PostalCode
often immutable
often in method parameters
have identity, we compare them using it
our crucial concepts are most likely Entities
similar to EJB or DB entities but POJOs
object graphs and/or groups (of VOs and entities)
untouchable, immutable - outside of it you work on copies
this we use to model our domain
root of the aggregates serves as point of entry
said root is an entity and contains operations on the aggregate
ensures data correctness and consistency through its operations
keeps system invariants
uses delegation and composition
this is why we have rich domain model
if A grows, B decreases
you can’t do X twice in a row
realizes persistence
works with infra-objects, like DAO, ORMs code
abstracts away the specifics
encapsulates data access and related logic
nowadays in some cases interchangeable with DAO
a design pattern, that introduces a new layer
for operations that don’t belong to any entity - and hence to no aggregates either
produce aggregates, ensuring their correctness
codifies creation logic, so usually some construction DPs are involved
increases testability, decreases complexity, extracts creational details
sagas
specifications
policies
services
Not today, but do read about them
The setting in which a word or a statement appears that determines its meaning
Eric Evans would say: cannot change the meaning
Draw what you know. Send to next person and ask him to fill something till insert date here. Rinse and repeat.
Bounded contexts should have a name so that you can talk about them.
Separates on multiple levels:
mental - different thinking
architectural - different system invariants or requirements
organizational - different teams, departments, locations
vocabulary - same term has different meaning
code - same object has different fields/methods
Distilling domains
Drawing context map
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
Requires one manager for all teams
here: strategic pattern
usually via proxy
translation / protection layer
you shall not pass, you abstraction from another bounded context you
if shared DB - wrong
if shared aspect - all right
partnership between teams needed
independent teams, independent software
happens to the best of us
just isolate it and make sure it doesn’t contaminate others
did someone just said "integration deadline"? |
one team must conform to the other
sucks to be on that team if the others are not playing nice
ACL all the things!
fairly straightforward relationship
web-services are a fine example
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
Hard to spot without answering "how the org wants to use software to leverage their strategy?"
why write and NOT buy or outsource?
accounting, ERP - unless you’re in accounting of course
share/like/social integration - unless you sell it
off the shelf, outsource - sure
accounting, ERP - unless you’re in accounting of course
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 |
terms change their meanings between contexts, but NOT inside
no leaks - context dictates what you mean when you say "student"
separation of concerns
YAGNI
context map makes the boundaries explicit
Census System – Address
is unique, so an entity
Book Rental - Address
is just a part of LibraryUser
, so a VO
Student in financial context has a name, surname, index number and an account.
Student in student records has no bank account, but has courses and grades
Account in profiling and in payments
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.
it’s called 'model exploration' technique
it uses storytelling and customer interviews
mistakes are taken into account through iterations
new scenarios should unearth them
new insights yield better questions and vocab
obviously dependent on domain experts available
team talks about FakeOrder
or TempItem
(no relation to business domain)
Scrum Velocity drops, lavaflow kicks in
we start hacking around our too complex model
accidental complexity rises, so does technical debt
expert and us flesh out a story - business processes descriptions
model is built, with state changes
code probe delivers services, class headers - walking skeleton approach
we formalize the scenario through live docs - BDD tests
BDD and acceptance scenario
Given
(Expert) - When
(Programmer) - Then
(Expert)
or how to use post-its for everything
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? |
who has the knowledge
different teams
mesh them together
there’s more than 4 steps but we don’t have time |
silos / Conway’s law within org
business to IT communication
measuring / testing the model
transition from model to code
fishing for facts to model / domain know-how
simplifying the domain
unambiguous language
ubiquitous language
contexts, bounded
solved
strategic patterns
context mapping for bounded contexts
solved
no communication problems
little / no primitives in code
connascence
solved
whirlpool
TDD, BDD, ATDD
testing bounded contexts
in isolation
as black boxes if needed
tactical patterns
building blocks
solved
smaller accidental - we model less
essential may be reduced by distilling the domain
building blocks / tactical patterns
isolation with layers / boundaries
solved
event storming
whirlpool
old techniques still valid
solved
And which dominates in practice?
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
tech-packages screw encapsulation
default
was never meant to be public
functional packages mean package access is fine
everything to everything, so why not call what shouldn’t be called?
no behaviours, just state manipulation, domain expresses nothing
changing behaviours is constant, but with state manipulation?
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
}
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();
returns void
,
input has no candidates
classic trains, to get to the candidate
not here, not all, but some
slight variations in their calls? sure
parameterless c-tor call
little subclassing, so EmployeeType
set regardless of isPermanent
seniority sometimes would be in the job title
location wasn’t conceptualized, so we would set:
country and region and city and postal-code sometimes
company and department
rate was virtually always displayed in local rates
some customers had distributed departments, some had them 'uni-located'
vacancy, job offer, applicant, candidate, posting, advertisement, position
Employee newHire = candidate.hire();
same logic every time, codified
on a Candidate, not a side-effect when closing Acquisition
business language maps to object.method() - ubiquitous language
easier to grasp and learn the relevant domain process
identify concepts and wrap them
extract classes, note variants and deal with them
connected objects should stay connected - use aggregates
transform the aggregate A into aggregate B with a service if needed
stay within boundaries of your current context
go across boundaries according to proper procedures
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);
}
}
1 | different names for same location - no longer a problem if this would be done cleverly |
2 | there are cases when candidates look for a job in a given radius |
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)
}
1 | cause various dinars (and few others) don’t have 1:100 step |
2 | and now currency is unchangeable and may be immutable (like enum ) |
3 | possible to add currency conversions, raises, spreads, etc., just return a new Rate object, changed appropriately |
ubiquitous language
prose in the code
business talks, dev maps to object.method call
rich domain model - has behaviours
easy reading / changing
harder for lazyness, fear or difficulties to make one reluctant to change the code
so strong as your domain expert’s knowledge - more of a limitation
most people stop at tactical level
Team skills and domain expert know-how are primary factors.
Software Development Life Cycle
idea → requirements
design (modelling)
coding → testing
deployment
maintenance
sunsetting the product
All of them if we want. Most of them if done somewhat right.
Symbiotic or friendly technologies and solutions may increase the effect.
layered architecture
hexagon architecture, or ports and adapters
well-done OOP (encapsulation, no/little state-sharing)
BDD, ABDD, ATDD and relevant libraries
microservices if done right (as well as our modelling)
strong domain experts
DDD actually is tech-agnostic.
domain expert
distilling domain (core, support…)
whirlpool, event storming
ubiquitous, unabiguous language
whirlpool
event storming
language
domain focus
rich domain model
building blocks
patterns (tactical and design)
clear code through building blocks
reflects domain so strong and protected invariants
domain truths usually coded down
bounded contexts and ACLs
strategic patterns help form cooperation rules between departments
acceptance tests
behaviour-driven tests
'normal', unit- and or system tests
easier integration tests - bounded contexts
may be easier if contexts separated
with good µservices where 1 µserv. means 1 bounded context - easy
with distributed monolith usually somewhat harder
least gain per se
Helps through all the phases of SDLC
Strategic, tactical, language, model
Event storming, whirlpool, context map
technology-agnostic
domain-centric
one language to rule them all
if existing project - get a word cloud from code to see concepts and try finding your ubiquitous language terms that way
Coupling, cohesion - meh
Connascence - better
Function-centric packages, not technical ones
Code is a prose
Good OOP
have names
keep meaning true
are multi-level: org, mental, vocab…
minimum aggregate is one entity
minimum context is one aggregate…
VO and Entities together create Aggregates
Factories encapsulate creation logic
Repositories abstract away data persistence access layer
There’s more
org structure will influence your contexts
ubiquitous, unabimguous language
between contexts: relationships
Anti-Corruption Layer protects meaning from leaking or changing
Continuous Integration supports heavy and non-stop cooperation
Customer - Supplier is BAU
Conformist is when it goes to hell (bad Supplier)
There’s more
core, support, generic
invest in core, buy generic
change in time
distilling may cut complexity
CRC, UML, C4
storytelling, requirements discovery, customer interview
whirlpool, context map, event storming
can be found after several aggregates are drawn
can be seen after event streams in event storming are done
makes concepts visible, can help with domain distilling
draw what you will
pass to next person so he can do the same
collect or wait once it gets back
gather reqs for target architecture
group people, reserve 3 hours
each group designs and presents, questions are a must
You can also hire Tomek to facilitate
start with VOs, identify - name - codify
entites next
aggregates are key
1 entity == min aggregates
1 aggregate == min bounded context
then services and more advanced tactics
start with modelling, it’s number 1
context map - distill domains
event storm - find aggregates, choke points
whirlpool - steady influx of terms to language
ubiquitous and unabigous language
perhaps hexagon, it won’t auto-evolve
test with TDD/ATDD/BDD to prove your model