Ur Domain Haz Monoids?
Cyrille Martraire - @cyriux
"My first encounter with FP concepts was from
DDD"
A matter of Taste
http://rosshirt.blogspot.fr/
The CodeGourmet
(dedicated to @ziobrando)
FP
Passionate developer
PARISSince 1999
@cyriuxCyrille Martraire
Paris Software Craftsmanship Community
http://www.meetup.com/paris-software-craftsmanship/
TDDBDDDDDLegacy
WARNINGThe following show features no spectacular stunt, no live coding, only trivial Java code. You can re-create or re-enact at home with no danger.
a bit personal
Adopted 2005Still in love
...
What do DDD & FP have in common?
FP = ?
http://www.jaider.net/archives/609-intro-to-functional-programming/
PURE
No StateNo War
So what do DDD & FP
have in common?
Value Objects................................................................................................. 19
Learn oneand get the other
one for FREE!
DDDFP
(OO)
NICE STYLE
of code
DDD+FP = ?
Example PLZ?
MONOIDZ!
@cyriux
ClosureAssociativity
Neutral Element
only 3 numbers in
programming
0, 1, MANY
Monoid:encapsulate
diversity inside
0, 1, MANY
Neutral Element
Element
Operation
Battle against complexity
Encapsulate details (unit...)
→ simple again
For a given interface I find myself doing often 0, 1, Many
OO FTW!
0, 1, MANY
NullObject
Implementation(s)
Composite
Identity Element
= NullObject
VatCalculation.NONE
Applied often:
→ scalable process
→ can grow to very complex complexity
Example PLZ!
Numbersint+int=int
(3+5)+2=3+(5+2)0
Lists
(.)+(.,.)=(.,.,.) ︎(a ︎)+(b,︎c)=(a ︎, b)+(c) ︎
()
Strings
"hello"+"world""cy"+"ri"+"lle"
""
look simplistic;the key to very
complex behavior
The key to infinite scalability!
The key to infinite incremental computing!
Hadoop x Storm
Composeability
Monoids ☛ reduce
Monoids ☛ domain
Monoids are typical FP
FP: everything is a value
Therefore:Monoids are
values!
VALUEOBJECTS
ImmutableEquals by value
Not Anemic
18°C+ 16°C= 34°C
returns a new instance
Change -> new instance
SIDE-EFFECT -free
FUNCTIONS
Immutability&
Side-effect-free functions!
Value Object
A DDD patternto import FP-ish
values in OO languages
“Functional-First” style
90%“Functional-First” style
Value Objects
(Ok, gut feeling, I did’nt measure)
Money
(25, EUR)+
(30, EUR)=
(55, EUR)
(25, EUR)+
(30, USD)=
exception
Money
amountcurrencyadd(Money): Money
<<ValueObject>>
Cashflows (Payments)
(25, EUR, today)+
(30, EUR, today)=
(55, EUR, today)
(25, EUR, today)+
(30, EUR, next day)=
exception
CashFlow
amountcurrencydate
add(CashFlow):CashFlow
<<ValueObject>>
CLOSURE of
OPERATION
Cashflows Sequences
(10, EUR, 20/03)
(30, EUR, 21/03)
(25, EUR, 21/03)
(12, EUR, 22/03)
(10, EUR, 20/03)
(55, EUR, 21/03)
(12, EUR, 22/03)
+
=
Cashflow Sequence +
Cashflow Sequence =
Cashflow Sequence
ObjectArithmetics
This is how domain experts THINK
about itSAY
SKETCH
Ranges
[1, 3]Union [2, 4]
= [1, 4]
[1, 3]Union [2, 4]
= [1, 4] ][
Predicates
FilterAND Filter
= Filter
FilterAND Filter
= Filter
Always
True
FilterOR
Filter=
Filter
FilterOR
Filter=
FilterAlways
False
Grants
Read, Write, Execute
"most secure wins"
r + w = rw + x = w
Configuration Maps
+
=
Color BLUE
Enable TrueTimeout 30 +
=
Color RED
Enable FalseTimeout 25
Desk FX
Color RED
Enable TrueTimeout 25
Desk FX
Default Desk-specific
+
=
Color BLUE
Enable TrueTimeout 30 +
=
Color RED
Enable FalseTimeout 25
Desk FX
Color RED
Enable TrueTimeout 25
Desk FX
Default Desk-specific
overw
rite
logic
al OR
min
+
=
Color BLUE
Enable TrueTimeout 30 +
=
Color RED
Enable FalseTimeout 25
Desk FX
Color RED
Enable TrueTimeout 25
Desk FX
Default Desk-specific
overw
rite
logic
al OR
min
Values are monoids too!
+
=
Color BLUE
Enable TrueTimeout 30 +
=
Neutral Element
Color BLUE
Enable TrueTimeout 30
+
=
Color BLUE
Enable TrueTimeout 30 +
=Color BLUE
Enable TrueTimeout 30
Value Objects may be
*BIG* object trees!
(DOM)
Non-Linear Stuff(average, std dev,
K-clustering, barycenters...)
Average + Average = WRONG
Average + Average Not Composeable!
avg = sum / count
avg = sum / count
avg = sum / count
avg = sum / count+
avg = sum / count
avg = sum / count+ +
avg = sum / count
avg = sum / count
avg = sum / count
+
=
+
=
(sum, count)
(sum, count)
(sum, count)
+
=
Average
(sum, sum2, count)
(sum, sum2, count)
(sum, sum2, count)
+
=
Std deviation
Can model as a monoid even non-
linear stuff!
MOARMATHS
PLZ!
Monoid several times...
toString(): Stringunion(MailingList): MailingListintersection(MailingList): MailingListnobody(): MailingListeverybody(): MailingList
MailingList
Space Vectors
average temperature = t1.add(t2) .scale(1/2)
returns a new instance
Change -> new instance
Space Vector
toCelsius(): TemperaturetoFarenheit(): Temperatureadd(Temperature): Temperaturescale(double): Temperature
Temperature
Why is it useful?
(10, EUR, 20/03)
(30, EUR, 21/03)
(25, EUR, 21/03)
(12, EUR, 22/03)
(10, EUR, 20/03)
(55, EUR, 21/03)
(12, EUR, 22/03)
+
=
Cashflow Sequence +
Cashflow Sequence =
Cashflow Sequence
This is how domain experts THINK
about itSAY
SKETCH
DECLARATIVE STYLE
Much less codeMuch less bugs
// without monoidsPaymentsFees(...)PaymentsFeesWithOptions(...)PaymentsFeesWithInsuranceAndOptions(...)PaymentsFeesWithInsurance(...)NoFeesButInsurance(...)...
// with monoidsfees(...) : Paymentsoptions(...) : Paymentsinsurance(...) : Payments
Payments.add(Payments) : Payments
side-effect-free
operation
Very easy to test
input output
Much less stuff to learn
1 interface to rule them all
Cashflow Sequence +
Cashflow Sequence =
Cashflow Sequence
ESTABLISHEDFORMALISMS
Monoid/Vector Spaces/Cyclic Group
LiteratureDocumented
@annotations
@Monoid()intersection(MailingList): MailingList
@NeutralElement("intersection")nobody(): MailingList
MailingList
LIVINGDOCUMENTATION
Signal to Noise ratio
http://www.flickr.com/photos/28471130@N07/2666802097
Signal to Noise Ratio
• SNR ≥ 80 %
• Signal (VO): CashFlow.multiply(), CashFlowSequence.add(), .negate(), truncate(), Money.add(), .times(), .opposite(), Fixing, FinancialProduct, BankHolidays, ReferenceData
• Noise: CashFlowBuilder, CompositeEngine, ProductFactory, BankHolidaysDecorator
Write code that tells the business
domain stories
@annotations
@Monoid()intersection(MailingList): MailingList
@NeutralElement("intersection")nobody(): MailingList
MailingList
Domain-Specific
@Monoid()overlaping(MailingList): MailingList
@NeutralElement("overlaping")nobody(): MailingList
MailingList
Value Objects have domain-specific
flavors too:
Convention, Policy, Status, Quantity,
Observation...
- Annotate domain-relevant classes
- Custom Doclet to export Excel-formatted glossary of every domain concept
Glossary from Code
Sent directly to end customers
Glossary from Code
SELF-EXPLAINING VALUES
We Want:Traceability of processing
No worry!
Just enrich our types
Just enrich our types
Just enrich our types
label field
Monad-ishNo logging neededEach value stores
its history
http://stuartcook.files.wordpress.com/2010/11/happy-monkey.jpg
In Closing
Invest time:
Learn DDD, and get free FP exposure
A paradox:
FP influence helps craft better Object-
Oriented code!
Monoids are good: Eat Them!
LOOK 4 Ur DOMAIN MONOIDZ!
Also learn other maths structures
Wikipedia is your friend!
DDD+FP=
http://wadler.blogspot.fr/2008/04/functional-programming-is-beautiful.html
Taste-Driven Development
TDD
Questions? Did you try similar things too?
Let’s discuss!
@cyriux
Follow me @cyriux
Slides: slideshare.net/cyriux
Blog: cyrille.martraire.com
In Paris? Join !
Merci