SlideShare ist ein Scribd-Unternehmen logo
1 von 95
Downloaden Sie, um offline zu lesen
Domain Modeling
With Functional Programming
(DDD Europe 2020)
@ScottWlaschin
fsharpforfunandprofit.com
Functional
Programming
Domain
Driven
Design
FP is good for:
‱ Interactive & collaborative domain modeling
‱ Representing a domain model accurately
Part I
The importance of design
Input Output
Process
The software development process
Input Output
Process
The software development process
Input Output
Process
Garbage in Garbage out
The software development process
Input Output
Process
(reduce) Garbage in (reduced) Garbage out
The software development process
‱ Agile contribution:
– Rapid feedback during design
‱ DDD contribution:
– Stakeholders have a shared mental model
– 
which is also represented in the code
How can we do design right?
Can you really make code
represent the domain?
What non-developers think source code looks like
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight
| Nine |Ten | Jack | Queen | King
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = Deck –â€ș (Deck * Card)
type PickupCard = (Hand * Card) –â€ș Hand
Sharedlanguage What DDD source code should look like
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight
| Nine |Ten | Jack | Queen | King
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = Deck –â€ș (Deck * Card)
type PickupCard = (Hand * Card) –â€ș Hand
* means a pair. Choose one from each type
list type is built in
Deal
(original)
Deck
(remaining)
Deck
(on table)
Card
Modeling an action with a function
type Deal = Deck -> (Deck * Card)
Input Output
Pickup Card
(updated)
Hand
(original)
Hand
(on table)
Card
Modeling an action with a function
type PickupCard = (Hand * Card) –> Hand
Input Output
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight
| Nine |Ten | Jack | Queen | King
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = Deck –â€ș (Deck * Card)
type PickupCard = (Hand * Card) –â€ș Hand
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight
| Nine |Ten | Jack | Queen | King
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = Deck –â€ș (Deck * Card)
type PickupCard = (Hand * Card) –â€ș Hand
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight
| Nine |Ten | Jack | Queen | King
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = Deck –â€ș (Deck * Card)
type PickupCard = (Hand * Card) –â€ș Hand
Can non-programmers provide
useful feedback?
Rapid feedback during
the design stage
Building a shared mental model is an
interactive process
...
type Deck = Card list
type Deal = Deck –â€ș (Deck * Card)
...
type Deck = Card list
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
...
type Deck = Card list
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
...
type Deck = Card list
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
type Shuffle = Deck –â€ș ShuffledDeck
...
type Deck = Card list
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
type Shuffle = Deck –â€ș ShuffledDeck
Final version of the domain
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight | ...
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
type Shuffle = Deck –â€ș ShuffledDeck
type PickupCard = (Hand * Card) –â€ș Hand
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight | ...
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
type Shuffle = Deck –â€ș ShuffledDeck
type PickupCard = (Hand * Card) –â€ș Hand
In the real world
Suit
Rank
Card
Hand
Deck
Player
Deal
In the code
Suit
Rank
Card
Hand
Deck
Player
Deal
In the real world
Suit
Rank
Card
Hand
Deck
Player
Deal
In the code
Suit
Rank
Card
Hand
Deck
Player
Deal
ShuffledDeck
Shuffle
ShuffledDeck
Shuffle

In the real world
Suit
Rank
Card
Hand
Deck
Player
Deal
In the code
Suit
Rank
Card
Hand
Deck
Player
Deal
PlayerController
DeckBase
AbstractCardProxyFactoryBean

module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight | ...
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
type Shuffle = Deck –â€ș ShuffledDeck
type PickupCard = (Hand * Card) –â€ș Hand
module CardGame =
type Suit = Club | Diamond | Spade | Heart
type Rank = Two |Three | Four | Five | Six | Seven | Eight | ...
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name:string; Hand:Hand }
type Game = { Deck:Deck; Players: Player list }
type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
type ShuffledDeck = Card list
type Shuffle = Deck –â€ș ShuffledDeck
type PickupCard = (Hand * Card) –â€ș Hand
The process of building the shared
mental model is critical!
Collaboration!
Key DDD principle:
Communicate the design
in the code
A domain modeling challenge!
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
} // true if ownership of
// email address is confirmed
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
Prologue: which values are optional?
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
Prologue: what are the constraints?
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
Prologue: domain logic?
Prologue: F# can help
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
Prologue: F# can help
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
Part II
Understanding FP type systems
FP principle:
Composition everywhere
Composition = Make big things from small things
Algebraic type system
New types are built from smaller types by:
Composing with “AND”
Composing with “OR”
FruitSalad = One each of and and
Compose with “AND”
type FruitSalad = {
Apple: AppleInfo
Banana: BananaInfo
Cherry: CherryInfo
}
Snack = or or
Compose with “OR”
type Snack =
| Apple of AppleInfo
| Banana of BananaInfo
| Cherry of CherryInfo
Part III
Domain modeling
with composable types
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
} // true if ownership of
// email address is confirmed
This looks suspiciously like database-driven design...
Conversation-driven design
Conversation-driven design
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
"A contact has a name AND email address"
"Like this?..."
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
"A contact has a name AND email address"
We have two new concepts already!
type PersonalName = {
FirstName: string
MiddleInitial: string
LastName: string
}
"What's a personal name?"
type PersonalName = {
FirstName: string
MiddleInitial: string
LastName: string
}
required
required
optional
"What's required or optional?"
Modeling
optional values
type Option<'T> =
| Some of 'T
| None
type PersonalName = {
FirstName: string
MiddleInitial: Option<string>
LastName: string
}
type PersonalName = {
FirstName: string
MiddleInitial: string option
LastName: string
}
Modeling simple values and
constrained values
Modeling simple values
‱ Avoid "Primitive Obsession"
‱ Simple values should not be modelled with
primitive types like "int" or "string" or "float"
"Does 'float' have
something to do
with water?"
Modeling constrained values
‱ It's rare to have an unconstrained int or string:
– An EmailAddress must not be empty,
it must match a pattern
– A PhoneNumber must not be empty,
it must match a pattern
– A CustomerId must be a positive integer
Is an EmailAddress just a string? No!
Is a CustomerId just a int? No!
type EmailAddress = EmailAddress of string
Use wrapper types to keep domain concepts
distinct from their representation
type CustomerId = CustomerId of int
type String50 = String50 of string
type EmailAddress = EmailAddress of string
type PhoneNumber = PhoneNumber of string
type CustomerId = CustomerId of int
type OrderId = OrderId of int
Two benefits:
- Clearer domain modelling
- Can't mix them up accidentally
The "Contact" challenge,
after first refactor
type Contact = {
FirstName: string
MiddleInitial: string
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
type Contact = {
FirstName: string
MiddleInitial: string option
LastName: string
EmailAddress: string
IsEmailVerified: bool
}
Use option type for
potentially missing values
type Contact = {
FirstName: String50
MiddleInitial: String1 option
LastName: String50
EmailAddress: EmailAddress
IsEmailVerified: bool
}
Use wrapper types
instead of primitives
type PersonalName = {
FirstName : String50
MiddleInitial : String1 option
LastName : String50 }
type EmailContactInfo = {
EmailAddress : EmailAddress
IsEmailVerified : bool }
Aggregates a.k.a. "consistency boundaries"
2 different
domain concepts
Replacing flags with choices
What about this?
type EmailContactInfo = {
EmailAddress : EmailAddress
IsEmailVerified : bool }
‱ Rule 1: If the email is changed, the verified flag
must be reset to false.
‱ Rule 2: The verified flag can only be set by a
special verification service
type EmailContactInfo = {
EmailAddress : EmailAddress
IsEmailVerified : bool }
"Email contact info is either Verified OR Unverified"
Listen closely to what the domain expert says...
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
"Email contact info is either Verified OR Unverified"
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
"Email contact info is either Verified OR Unverified"
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
Q: Is a Verified email different?
Are there different business rules?
A: Yes, it must not be mixed up with unverified.
type VerifiedEmail = VerifiedEmail of EmailAddress
"there is no problem that can’t be
solved by wrapping it in another type"
type VerificationService =
(EmailAddress * VerificationHash) –â€ș VerifiedEmail option
Q: Where do we get Verified emails from?
A: A special verification process
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type VerificationService =
(EmailAddress * VerificationHash) –â€ș VerifiedEmail option
Q: Are the business rules clear now?
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type VerificationService =
(EmailAddress * VerificationHash) –â€ș VerifiedEmail option
Those business rules are automatically enforced by the design!
The "Contact" challenge,
completed
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
type PersonalName = {
FirstName: String50
MiddleInitial: String1 opt
LastName: String50 }
type Contact = {
Name: PersonalName
Email: EmailContactInfo }
type EmailAddress = ...
type VerifiedEmail =
VerifiedEmail of EmailAddress
type EmailContactInfo =
| Unverified of EmailAddress
| Verified of VerifiedEmail
Summary
‱ Represent the shared mental model in code
– The developers should become domain experts too
– Write code collaboratively to build the shared
mental model
‱ Use the power of a composable type system
– Options instead of null
– Wrappers for constrained types
– Choice types rather than inheritance or flags
– Static types give you confidence when refactoring
More "Domain Modeling Made Functional" at
– fsharpforfunandprofit.com/ddd
Thanks!
Twitter: @ScottWlaschin

Weitere Àhnliche Inhalte

Was ist angesagt?

The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsScott Wlaschin
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Scott Wlaschin
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Scott Wlaschin
 
Monadic Java
Monadic JavaMonadic Java
Monadic JavaMario Fusco
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)Scott Wlaschin
 
Haskell vs. F# vs. Scala
Haskell vs. F# vs. ScalaHaskell vs. F# vs. Scala
Haskell vs. F# vs. Scalapt114
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 
The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)Scott Wlaschin
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
Escrevendo códigos php seguros
Escrevendo códigos php segurosEscrevendo códigos php seguros
Escrevendo códigos php segurosDouglas V. Pasqua
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional WorldDebasish Ghosh
 
Introduction to Actor Model and Akka
Introduction to Actor Model and AkkaIntroduction to Actor Model and Akka
Introduction to Actor Model and AkkaYung-Lin Ho
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with CapabilitiesScott Wlaschin
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeScott Wlaschin
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Metosin Oy
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesLauren Yew
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlinintelliyole
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvCodelyTV
 

Was ist angesagt? (20)

The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)
 
Haskell vs. F# vs. Scala
Haskell vs. F# vs. ScalaHaskell vs. F# vs. Scala
Haskell vs. F# vs. Scala
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Escrevendo códigos php seguros
Escrevendo códigos php segurosEscrevendo códigos php seguros
Escrevendo códigos php seguros
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
 
Introduction to Actor Model and Akka
Introduction to Actor Model and AkkaIntroduction to Actor Model and Akka
Introduction to Actor Model and Akka
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with Capabilities
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytv
 

Ähnlich wie Domain Modeling with FP (DDD Europe 2020)

Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Scott Wlaschin
 
project 6cards.pyimport randomclass Card( object ).docx
project 6cards.pyimport randomclass Card( object ).docxproject 6cards.pyimport randomclass Card( object ).docx
project 6cards.pyimport randomclass Card( object ).docxbriancrawford30935
 
Domain typing in Ruby
Domain typing in RubyDomain typing in Ruby
Domain typing in RubySergiy Kukunin
 
FaceUp card game In this assignment we will implement a made.pdf
FaceUp card game In this assignment we will implement a made.pdfFaceUp card game In this assignment we will implement a made.pdf
FaceUp card game In this assignment we will implement a made.pdfabifancystore
 
This is the final code which meets your requirement.Than youCard.j.pdf
This is the final code which meets your requirement.Than youCard.j.pdfThis is the final code which meets your requirement.Than youCard.j.pdf
This is the final code which meets your requirement.Than youCard.j.pdfaplolomedicalstoremr
 
Intellectual playing cards - Not for everyone
Intellectual playing cards - Not for everyoneIntellectual playing cards - Not for everyone
Intellectual playing cards - Not for everyonedrstevenquay
 

Ähnlich wie Domain Modeling with FP (DDD Europe 2020) (6)

Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
project 6cards.pyimport randomclass Card( object ).docx
project 6cards.pyimport randomclass Card( object ).docxproject 6cards.pyimport randomclass Card( object ).docx
project 6cards.pyimport randomclass Card( object ).docx
 
Domain typing in Ruby
Domain typing in RubyDomain typing in Ruby
Domain typing in Ruby
 
FaceUp card game In this assignment we will implement a made.pdf
FaceUp card game In this assignment we will implement a made.pdfFaceUp card game In this assignment we will implement a made.pdf
FaceUp card game In this assignment we will implement a made.pdf
 
This is the final code which meets your requirement.Than youCard.j.pdf
This is the final code which meets your requirement.Than youCard.j.pdfThis is the final code which meets your requirement.Than youCard.j.pdf
This is the final code which meets your requirement.Than youCard.j.pdf
 
Intellectual playing cards - Not for everyone
Intellectual playing cards - Not for everyoneIntellectual playing cards - Not for everyone
Intellectual playing cards - Not for everyone
 

Mehr von Scott Wlaschin

Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Scott Wlaschin
 
Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)Scott Wlaschin
 
Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)Scott Wlaschin
 
Four Languages From Forty Years Ago
Four Languages From Forty Years AgoFour Languages From Forty Years Ago
Four Languages From Forty Years AgoScott Wlaschin
 
F# for C# Programmers
F# for C# ProgrammersF# for C# Programmers
F# for C# ProgrammersScott Wlaschin
 
Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Scott Wlaschin
 
Thirteen ways of looking at a turtle
Thirteen ways of looking at a turtleThirteen ways of looking at a turtle
Thirteen ways of looking at a turtleScott Wlaschin
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterScott Wlaschin
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testingScott Wlaschin
 
Swift vs. Language X
Swift vs. Language XSwift vs. Language X
Swift vs. Language XScott Wlaschin
 
Doge-driven design
Doge-driven designDoge-driven design
Doge-driven designScott Wlaschin
 
The Theory of Chains
The Theory of ChainsThe Theory of Chains
The Theory of ChainsScott Wlaschin
 

Mehr von Scott Wlaschin (12)

Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...
 
Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)
 
Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)
 
Four Languages From Forty Years Ago
Four Languages From Forty Years AgoFour Languages From Forty Years Ago
Four Languages From Forty Years Ago
 
F# for C# Programmers
F# for C# ProgrammersF# for C# Programmers
F# for C# Programmers
 
Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)
 
Thirteen ways of looking at a turtle
Thirteen ways of looking at a turtleThirteen ways of looking at a turtle
Thirteen ways of looking at a turtle
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the Monadster
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testing
 
Swift vs. Language X
Swift vs. Language XSwift vs. Language X
Swift vs. Language X
 
Doge-driven design
Doge-driven designDoge-driven design
Doge-driven design
 
The Theory of Chains
The Theory of ChainsThe Theory of Chains
The Theory of Chains
 

KĂŒrzlich hochgeladen

LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456KiaraTiradoMicha
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Chinsurah Escorts ☎8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎8617697112 Starting From 5K to 15K High Profile Escorts ...Nitya salvi
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyAnusha Are
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedDelhi Call girls
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfWilly Marroquin (WillyDevNET)
 

KĂŒrzlich hochgeladen (20)

LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Chinsurah Escorts ☎8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎8617697112 Starting From 5K to 15K High Profile Escorts ...
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 

Domain Modeling with FP (DDD Europe 2020)

  • 1. Domain Modeling With Functional Programming (DDD Europe 2020) @ScottWlaschin fsharpforfunandprofit.com
  • 3. FP is good for: ‱ Interactive & collaborative domain modeling ‱ Representing a domain model accurately
  • 5. Input Output Process The software development process
  • 6. Input Output Process The software development process
  • 7. Input Output Process Garbage in Garbage out The software development process
  • 8. Input Output Process (reduce) Garbage in (reduced) Garbage out The software development process
  • 9. ‱ Agile contribution: – Rapid feedback during design ‱ DDD contribution: – Stakeholders have a shared mental model – 
which is also represented in the code How can we do design right?
  • 10.
  • 11.
  • 12. Can you really make code represent the domain?
  • 13. What non-developers think source code looks like
  • 14. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | Nine |Ten | Jack | Queen | King type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = Deck –â€ș (Deck * Card) type PickupCard = (Hand * Card) –â€ș Hand Sharedlanguage What DDD source code should look like
  • 15. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | Nine |Ten | Jack | Queen | King type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = Deck –â€ș (Deck * Card) type PickupCard = (Hand * Card) –â€ș Hand * means a pair. Choose one from each type list type is built in
  • 16. Deal (original) Deck (remaining) Deck (on table) Card Modeling an action with a function type Deal = Deck -> (Deck * Card) Input Output
  • 17. Pickup Card (updated) Hand (original) Hand (on table) Card Modeling an action with a function type PickupCard = (Hand * Card) –> Hand Input Output
  • 18. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | Nine |Ten | Jack | Queen | King type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = Deck –â€ș (Deck * Card) type PickupCard = (Hand * Card) –â€ș Hand
  • 19. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | Nine |Ten | Jack | Queen | King type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = Deck –â€ș (Deck * Card) type PickupCard = (Hand * Card) –â€ș Hand
  • 20. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | Nine |Ten | Jack | Queen | King type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = Deck –â€ș (Deck * Card) type PickupCard = (Hand * Card) –â€ș Hand Can non-programmers provide useful feedback?
  • 22. Building a shared mental model is an interactive process
  • 23. ... type Deck = Card list type Deal = Deck –â€ș (Deck * Card)
  • 24. ... type Deck = Card list type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card)
  • 25. ... type Deck = Card list type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list
  • 26. ... type Deck = Card list type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list type Shuffle = Deck –â€ș ShuffledDeck
  • 27. ... type Deck = Card list type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list type Shuffle = Deck –â€ș ShuffledDeck
  • 28. Final version of the domain
  • 29. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | ... type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list type Shuffle = Deck –â€ș ShuffledDeck type PickupCard = (Hand * Card) –â€ș Hand
  • 30. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | ... type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list type Shuffle = Deck –â€ș ShuffledDeck type PickupCard = (Hand * Card) –â€ș Hand
  • 31. In the real world Suit Rank Card Hand Deck Player Deal In the code Suit Rank Card Hand Deck Player Deal
  • 32. In the real world Suit Rank Card Hand Deck Player Deal In the code Suit Rank Card Hand Deck Player Deal ShuffledDeck Shuffle ShuffledDeck Shuffle 
  • 33. In the real world Suit Rank Card Hand Deck Player Deal In the code Suit Rank Card Hand Deck Player Deal PlayerController DeckBase AbstractCardProxyFactoryBean 
  • 34. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | ... type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list type Shuffle = Deck –â€ș ShuffledDeck type PickupCard = (Hand * Card) –â€ș Hand
  • 35. module CardGame = type Suit = Club | Diamond | Spade | Heart type Rank = Two |Three | Four | Five | Six | Seven | Eight | ... type Card = Suit * Rank type Hand = Card list type Deck = Card list type Player = { Name:string; Hand:Hand } type Game = { Deck:Deck; Players: Player list } type Deal = ShuffledDeck –â€ș (ShuffledDeck * Card) type ShuffledDeck = Card list type Shuffle = Deck –â€ș ShuffledDeck type PickupCard = (Hand * Card) –â€ș Hand
  • 36. The process of building the shared mental model is critical! Collaboration!
  • 37. Key DDD principle: Communicate the design in the code
  • 38. A domain modeling challenge!
  • 39. type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool } // true if ownership of // email address is confirmed
  • 40. type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool } Prologue: which values are optional?
  • 41. type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool } Prologue: what are the constraints?
  • 42. type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool } Prologue: domain logic?
  • 43. Prologue: F# can help type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool }
  • 44. Prologue: F# can help type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool }
  • 45. Part II Understanding FP type systems
  • 47.
  • 48. Composition = Make big things from small things
  • 50. New types are built from smaller types by: Composing with “AND” Composing with “OR”
  • 51. FruitSalad = One each of and and Compose with “AND” type FruitSalad = { Apple: AppleInfo Banana: BananaInfo Cherry: CherryInfo }
  • 52. Snack = or or Compose with “OR” type Snack = | Apple of AppleInfo | Banana of BananaInfo | Cherry of CherryInfo
  • 53. Part III Domain modeling with composable types
  • 54. type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool } // true if ownership of // email address is confirmed This looks suspiciously like database-driven design...
  • 57. type Contact = { Name: PersonalName Email: EmailContactInfo } "A contact has a name AND email address" "Like this?..."
  • 58. type Contact = { Name: PersonalName Email: EmailContactInfo } "A contact has a name AND email address" We have two new concepts already!
  • 59. type PersonalName = { FirstName: string MiddleInitial: string LastName: string } "What's a personal name?"
  • 60. type PersonalName = { FirstName: string MiddleInitial: string LastName: string } required required optional "What's required or optional?"
  • 62. type Option<'T> = | Some of 'T | None
  • 63. type PersonalName = { FirstName: string MiddleInitial: Option<string> LastName: string }
  • 64. type PersonalName = { FirstName: string MiddleInitial: string option LastName: string }
  • 65. Modeling simple values and constrained values
  • 66. Modeling simple values ‱ Avoid "Primitive Obsession" ‱ Simple values should not be modelled with primitive types like "int" or "string" or "float" "Does 'float' have something to do with water?"
  • 67. Modeling constrained values ‱ It's rare to have an unconstrained int or string: – An EmailAddress must not be empty, it must match a pattern – A PhoneNumber must not be empty, it must match a pattern – A CustomerId must be a positive integer
  • 68. Is an EmailAddress just a string? No! Is a CustomerId just a int? No!
  • 69. type EmailAddress = EmailAddress of string Use wrapper types to keep domain concepts distinct from their representation type CustomerId = CustomerId of int type String50 = String50 of string
  • 70. type EmailAddress = EmailAddress of string type PhoneNumber = PhoneNumber of string type CustomerId = CustomerId of int type OrderId = OrderId of int Two benefits: - Clearer domain modelling - Can't mix them up accidentally
  • 72. type Contact = { FirstName: string MiddleInitial: string LastName: string EmailAddress: string IsEmailVerified: bool }
  • 73. type Contact = { FirstName: string MiddleInitial: string option LastName: string EmailAddress: string IsEmailVerified: bool } Use option type for potentially missing values
  • 74. type Contact = { FirstName: String50 MiddleInitial: String1 option LastName: String50 EmailAddress: EmailAddress IsEmailVerified: bool } Use wrapper types instead of primitives
  • 75. type PersonalName = { FirstName : String50 MiddleInitial : String1 option LastName : String50 } type EmailContactInfo = { EmailAddress : EmailAddress IsEmailVerified : bool } Aggregates a.k.a. "consistency boundaries" 2 different domain concepts
  • 77. What about this? type EmailContactInfo = { EmailAddress : EmailAddress IsEmailVerified : bool }
  • 78. ‱ Rule 1: If the email is changed, the verified flag must be reset to false. ‱ Rule 2: The verified flag can only be set by a special verification service type EmailContactInfo = { EmailAddress : EmailAddress IsEmailVerified : bool }
  • 79. "Email contact info is either Verified OR Unverified" Listen closely to what the domain expert says... type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 80. "Email contact info is either Verified OR Unverified" type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 81. "Email contact info is either Verified OR Unverified" type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 82. Q: Is a Verified email different? Are there different business rules? A: Yes, it must not be mixed up with unverified. type VerifiedEmail = VerifiedEmail of EmailAddress "there is no problem that can’t be solved by wrapping it in another type"
  • 83. type VerificationService = (EmailAddress * VerificationHash) –â€ș VerifiedEmail option Q: Where do we get Verified emails from? A: A special verification process
  • 84. type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail type VerificationService = (EmailAddress * VerificationHash) –â€ș VerifiedEmail option Q: Are the business rules clear now?
  • 85. type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail type VerificationService = (EmailAddress * VerificationHash) –â€ș VerifiedEmail option Those business rules are automatically enforced by the design!
  • 87. type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo }
  • 88. type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo }
  • 89. type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo } type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 90. type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo } type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 91. type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo } type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 92. type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo } type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 93. type PersonalName = { FirstName: String50 MiddleInitial: String1 opt LastName: String50 } type Contact = { Name: PersonalName Email: EmailContactInfo } type EmailAddress = ... type VerifiedEmail = VerifiedEmail of EmailAddress type EmailContactInfo = | Unverified of EmailAddress | Verified of VerifiedEmail
  • 94. Summary ‱ Represent the shared mental model in code – The developers should become domain experts too – Write code collaboratively to build the shared mental model ‱ Use the power of a composable type system – Options instead of null – Wrappers for constrained types – Choice types rather than inheritance or flags – Static types give you confidence when refactoring
  • 95. More "Domain Modeling Made Functional" at – fsharpforfunandprofit.com/ddd Thanks! Twitter: @ScottWlaschin