Fuctional Domain Modeling

19
Functional Domain Modeling By / Michal Bigos @teliatko

description

How to apply functional concepts in modeling domain objects. Examples are in Scala. Presented on Rubyslava / PyVo #32 (see http://lanyrd.com/2013/rubyslava-september)

Transcript of Fuctional Domain Modeling

Page 1: Fuctional Domain Modeling

Functional Domain

ModelingBy /

Michal Bigos @teliatko

Page 2: Fuctional Domain Modeling

Agenda1. Functional Programming Gems2. Example3. Perception of State4. What's Next...

Page 3: Fuctional Domain Modeling

Functional Programming GemsPure Functions

Functions w/o side-effectsThey are referentialy transparent

// Definition of functiondef someComputation(value: Long): Long = value + 3

// Definition as function literalval anotherComputation: (Long) => Long = (value: Long) => value + 3

Page 4: Fuctional Domain Modeling

Functional Programming GemsImmutable Data

Data w/o shared mutable stateThey can be shared freely ... no locks, no semafores etc.

// Definition of case objectssealed trait ProgrammingLanguageKindcase object Static extends ProgrammingLanguageKindcase object Dynamic extends ProgrammingLanguageKind

// Definition of case classcase class ProgrammingLanguage( name: String, kind: ProgrammingLanguageKind)

Page 5: Fuctional Domain Modeling

Functional Programming GemsPersistent Data Structures

Always preserves the previous version of itself when it ismodifiedEffectively immutable with no in-place mutation// Suppose we have a list...val l1 = List(1, 2, 3)

// Then we add a item to itval l2 = 4 :: l

assert(l1 != l2) // yields true

Page 6: Fuctional Domain Modeling

Functional Programming GemsAlgebraic Data Types, take one

An algebraic data type is a kind of composite type, i.e. a typeformed by combining other typesData types with some algebra, i.e. structure and operationsUnit type, Sum type and Product type

e.g. Lists can by formaly described as L = I + X * L

val emptyList = List() // Unit typeval simpleList = 1 :: emptyList // Sum typeval productList = 2 :: emptyList // Product type

Page 7: Fuctional Domain Modeling

Functional Programming GemsAlgebraic Data Types, take two

Domain entities are represented using product typescase classes are best fit in Scala

// Tuple is simplest product typeval programmingLanguage = (name, kind)

// Product type via case classcase class ProgrammingLanguage( name: String, kind: ProgrammingLanguageKind)

Page 8: Fuctional Domain Modeling

Functional Programming GemsAlgebraic Data Types, take three

Domain values and enums are represented using sum typesInheritance and sealed traits/classes are best fit in Scala// Example of sum-type, Option from Scala library (code simplified)sealed abstract class Option[+A]final case class Some[+A](x: A) extends Option[A]case object None extends Option[Nothing]

// Sum type via case objectssealed trait ProgrammingLanguageKindcase object Static extends ProgrammingLanguageKindcase object Dynamic extends ProgrammingLanguageKind

Page 9: Fuctional Domain Modeling

Functional Programming GemsFunction Composition

Functions compose when they cause no side-effectsSide-effects do not compose

scala> def foo(something: String): String = s"foo($something)"scala> def bar(something: String): String = s"bar($something)"

val composit = foo _ compose bar _val reverseComposit = foo _ andThen bar _

composit("anything") > foo(bar(anything))

reverseComposit("anything")> bar(foo(anything))

Page 10: Fuctional Domain Modeling

Functional Programming GemsCombinators

Apply high-order functionsGlue for chaining functionsPure functions as domain invariants and behavior

found map { foundLine => partitions.success } | | Combinator High-order fn

Monadic chaining, via for-comprehensionsfor { | _ <- quantityInvariant(quantity) _ <- priceInvariant(price) (found, rest) <- productAlreadyExists(productId)} yield { /* do something */}

Page 11: Fuctional Domain Modeling

Functional Programming GemsSide Effects

FP languages encourage isolating side-effects from puredomain logicKnown side-effects (not insignigicant)

1. DB access2. Logging3. IO operations

Exampleresult.foreach { case (order, event) => orderRepository.saveOrUpdate(order)}

Page 12: Fuctional Domain Modeling

Functional Programming GemsMore to cover

Ad-hoc polymorphism via Type ClassesType-Lenses functional updates in your domain model

Page 13: Fuctional Domain Modeling

Example

Page 14: Fuctional Domain Modeling

Perception of State

Domain state is effecively mutableCan retain previous statesHistory of what happenedIn-place mutation are wrong for domain modelThey combine state with time

Page 15: Fuctional Domain Modeling

What's nextEvent Sourcing

Every state-modification on domain yields eventDomain change is achieved by applying the event to theaggregateEvent stream, all the events applied on domain

Page 16: Fuctional Domain Modeling

What's nextCQRS

Commands execute operations on domain modelQueries arbitrary views of dataIndependent scalability

Page 17: Fuctional Domain Modeling

What's nextMemory Image and STM

Application state in memoryApplication of events to current state on domainEnables transactions on memory

Page 18: Fuctional Domain Modeling

Interesting Links

1. 2. 3. 4. 5. 6. 7. 8.

Pure Function (Wikipedia)Referenctial Transparency (Wikipedia)Persistent Data Structure (Wikipedia)Presistend Data Structures and Managed ReferencesADT, Product and Sum Types (Bob Harper, PFPL)Simple Made Easy (Rich Hickey)Function Composition (Wikipedia)Building Apps w/ Functional Domain Models (DebasishGhosh)

Page 19: Fuctional Domain Modeling

Thanks for your attention