SlideShare a Scribd company logo
Behind OOD
// domain modelling in a post-OO world
Ruslan Shevchenko
Lynx Capital Partners
https://github.com/rssh
@rssh1
Domain modelling
• Representation of business domain objects:
• in ‘head’ of people
• in code
Domain modelling.
• Outline typical OOD issues
• Build
• simple domain model for toy billing system.
// scala, can be mapped to java.
• internal DSL
Domain modelling
• Traditional OO way: have layer of classes,
which corresponds to domain objects.
• Extensibility via inheritance in some
consistent Universal Ontology
• Intensional Equality [identity != attribute]
• Object instance <=> Entity in real world
Traditional OO WAY
• Human is an upright, featherless biped with
broad, flat nails.
Traditional OO WAY
• Human is an upright, featherless biped with
broad, flat nails.
Open for extensions close for modifications
Traditional OO WAY
• Human is an upright, featherless biped with
broad, flat nails.
Open for extensions close for modifications
Traditional OO WAY
• Intensional Equality [ mutability ]
// same identity thought lifecycle
Traditional OO WAY
• Object in code <=> Object in real world
class Person {
int getId();
String getName();
int getAge();
Set<Person> getChilds()
}
— thread-safe ?
— persistent updates ?
Domain modelling
• Traditional OO way: have layer of classes,
which corresponds to domain objects.
• Extensibility via inheritance in some
consistent Universal Ontology
• Intensional Equality [identity != attribute]
• Object instance <=> Entity in real world
Domain modelling
• Traditional OO way: similar to early
philosophy
• Very general
• Idealistic
• Fit to concrete cases may be undefined
Domain modelling
• Post OO way: describe limited set of objects
and relationships.
• Algebra instead Ontology
• Existential equality [identity == same
attributes]
• Rules of algebra <=> rules of reality.
Domain modelling: where to start.
• Example: description of small billing system
Subscriber
Billing System
Service PaymentPlanuse
in accordance
with
Service is Internet | Telephony
PaymentPlan is Monthly Fee for Quantity Limit and
Overhead cost per Unit
Unit Internet is Gbin
Telephony is Minute
and Bandwidth
TariffPlan: Use limit and quantity from service.
sealed trait Service
{
type Limits
def quantity(l:Limits): BigDecimal
}
case object Internet extends Service
{
case class Limits(gb:Int,bandwidth:Int)
def quantity(l:Limits) = l.gb
}
case object Telephony extends Service
{
type Limits = Int
def quantity(l) = l
TariffPlan: Price per limit and charge
case class TariffPlan[Limits](
monthlyFee: BigDecimal,
monthlyLimits: Limits,
excessCharge: BigDecimal
)
Subscriber ? Service ?
case class Subscriber( id, name, … )
trait BillingService
{
def checkServiceAccess(u:Subscriber,s:Service):Boolean
def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber
def ratePeriod(u:Subscriber, date: DateTime)
def acceptPayment(u:Subscriber, payment: Payment)
}
// Aggregate
// let’s add to Subscriber all fields, what needed.
adding fields for Subscriber aggregates.
case class Subscriber(id, name,
serviceInfos:Map[Service,SubscriberServiceInfo],
account: BigDecimal, …..
)
case class SubscriberServiceInfo[S<:Service,L<:S#Limits](
service: S, tariffPlan: tariffPlan[S,L], amountUsed:Double
)
trait BillingService
{
def checkServiceAccess(u:Subscriber,s:Service):Boolean =
u.serviceInfos(s).isDefined && u.account > 0
}
adding fields for Subscriber aggregates.
case class Subscriber(id, name,
serviceInfos:Map[Service,SubscriberServiceInfo[_,_]],
account: BigDecimal, …..
)
case class ServiceUsage(service, amount, when)
trait BillingService
{
def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber =
serviceInfo(r.service) match {
case Some(SubscriberServiceInfo(service,plan,amount)) =>
val price = ….
u.copy(account = u.account - price,
serviceInfo = serviceInfo.updated(s,
}
adding fields for Subscriber aggregates.
trait BillingService
{
def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber =
serviceInfo(r.service) match {
case Some(SubscriberServiceInfo(service,plan,amount)) =>
val price = ….
u.copy(account = u.account - price,
serviceInfo = serviceInfo.updated(s,
ServiceInfo(service,plan,amount+r.amount))
)
case None =>
throw new IllegalStateException(“service is not enabled”)
}
…………….
}
Subscriber aggregates [rate: lastPayedDate]
case class Subscriber(id, name,
serviceInfos:Map[Service,SubscriberServiceInfo[_,_]],
account: BigDecimal,
lastPayedDate: DateTime
)
trait BillingService
{
def ratePeriod(u:Subscriber,date:DateTime):Subscriber =
if (date < u.lastPayedDate) u
else {
val price = …..
subscriber.copy(account = u.account - price,
lastPayedDate = date+1.month)
}
}
Subscriber:
case class Subscriber(
id : Long,
name: String,
serviceInfos:Map[Service,SubscriberServiceInfo[_,_]],
account: BigDecimal,
lastPayedDate: DateTime
)
case class SubscriberServiceInfo[S<:Service,L<:S#Limits](
service: S,
tariffPlan: tariffPlan[L],
amountUsed:Double
)
Subscriber:
case class Subscriber(
id : Long,
name: String,
internetServiceInfo: ServiceInfo[Internet,Internet.Limits],
telephonyServiceInfo: ServiceInfo[Telephony,Telephony.Limits],
account: BigDecimal,
lastPayedDate: DateTime
) {
def serviceInfo(s:Service):SubscriberServiceInfo[s.type,s.Limits] =
….
def updateServiceInfo[S<:Service,L<:S#Limits](
serviceInfo:SubscriberServiceInfo[S,L]): Subscriber =
…
}
From domain model to implementation. [S1]
Subscriber
Service TariffPlan
Domain Data/ Aggregates Services
SubscriberOperations
TariffPlanOperations
….
Repository
DD — contains only essential data
Services — only functionality
Testable.
No mess with implementation.
Service calls — domain events
From domain model to implementation. [S1]
Improvements/Refactoring space:
• Errors handling
• Deaggregate
• Fluent DSL
Errors handling (design for failure)
trait BillingService
{
def checkServiceAccess(u:Subscriber,s:Service):Boolean
def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber
def ratePeriod(u:Subscriber, date: DateTime): Subscriber
def acceptPayment(u:Subscriber, payment:Payment):Subscriber
}
Design for failure:
trait BillingService
{
def checkServiceAccess(u:Subscriber,s:Service): Boolean
def rateServiceUsage(u:Subscriber,r:ServiceUsage):Try[Subscriber]
def ratePeriod(u:Subscriber, date: DateTime): Try[Subscriber]
def acceptPayment(u:Subscriber, payment:Payment): Subscriber
}
Design for failure:
sealed trait Try[+X]
case class Success[X](v:X) extends Try[X]
case class Failure(ex:Throwable) extends Try[Nothing]
when use Try / traditional exception handling?
Try — error recovery is a part of business layers.
(i.e. errors is domain-related)
Exception handling — error recovery is a part of infrastructure layer.
(i. e. errors is system-related)
Deaggregation:
trait Repository
{
def create[T](): T
def find[T](id: Id[T]): Try[T]
def save[T](obj: T): Try[Boolean]
}
Deaggregation:
trait Repository
{
def create[T](): T
def find[T](id: Id[T]): Try[T]
def save[T](obj: T) : Try[T]
………..
def subscriberServiceInfo[S<:Service,L<:S#Limits]
(id: Id[Subscriber], s:S): SubscriberServiceInfo[S,L]
def updateSubsriberServiceInfo[S<:Service,L<:S#Limits] (
id: Id[Subscriber],s:S,si:SubscriberServiceInfo[S,L]):
Try[SubscriberServiceInfo[S,L]]
}
Deaggregation:
trait BillingService
{
def checkServiceAccess(r:Repository, uid:Id[Subscriber],
s:Service): Boolean
def rateServiceUsage(r: Repository, uid:Id[Subscriber],
r:ServiceUsage):Try[Subscriber]
…..
}
Deaggregation:
trait BillingService
{
val repository: Repository
def checkServiceAccess(uid:Id[Subscriber], s:Service): Try[Boolean]
def rateServiceUsage(uid:Id[Subscriber], r:ServiceUsage):Try[Subscriber]
…..
}
// BillingService operations interpret repository
Deaggregation. [S2]
Subscriber
Service TariffPlan
Domain Data/ Aggregates Services
SubscriberOperations
TariffPlanOperations
….
Repository
Interpret
- Not for all cases
- Loss
- generality of repository
- simply logic
- Gain
- simple repository operations
- more efficient data access.
DSL: Domain Specific Language.
Idea: fluent syntax for fluent operations.
• Syntax sugar, can be used by non-programmers
• ‘Micro-interpreter/compiler’
• Internal/External
Let’s build simple Internal DSL for our tariff plans.
TariffPlan: DSL
case class TariffPlan[Limits](
monthlyFee: BigDecimal,
monthlyLimits: Limits,
excessCharge: BigDecimal
)
TariffPlan(100,Limits(1,100),2)
TariffPlan(montlyFee=100,
Internet.Limits(gb=1,bandwidth=100),
2)
100 hrn montly (1 gb) speed 100 excess 2 hrn per 1 gb
// let’s build
TariffPlan: DSL
(100 hrn) montly (1 gb) speed 100 excess (2 hrn) per (1 gb)
trait TariffPlanDSL[S <: Service, L <: S#Limits] {
implicit class ToHrn(v: Int)
{
def hrn = this
def monthly(x: LimitExpression) =
TariffPlan(v, x.limit, 0)
def per(x: QuantityExpression
}
1 hrn = 1.hrn =
new ToHrn(1).hrn
trait LimitExpression{
def limit: L
}
type QuantityExpression
{
def quantity: Int
}
TariffPlan: DSL
(100 hrn) montly (1 gb) speed 100 excess (2 hrn) per (1 gb)
object InternetTariffPlanDSL extends TariffPlanDSL[Internet.type, Internet.Limits]
implicit class Gb(v: Int) extends LimitExpression with QuantityExpression{
def gb = this
def limit = Internet.Limits(v,100)
def quantity = x
}
TariffPlan: DSL
(100 hrn) montly (1 gb) speed 100 excess (2 hrn) per (1 gb)
(100 hrn) montly (1 gb) == (100.hrn).montly(1.gb)
TariffPlan: DSL
(100 hrn) montly (1 gb) speed 100 excess ((2 hrn) per (1 gb))
trait TariffPlanDSL[S,L]
case class PerExpression(money: ToHrn, quantity: QuantityExpression)
trait RichTariffPlan(p: TariffPlan[L]) {
def excess(x: PerExpression) = p.copy(excessCost=x.v)
}
((100.hrn).montly(1.gb) speed 100).excess((2 hrn) per (1 gb))
TariffPlan: DSL
(100 hrn) montly (1 gb) speed 100 excess ((2 hrn) per (1 gb))
object InternetTariffPlanDSL[S,L]
trait RichTariffPlan(p: TariffPlan[L]) extends super.RichTariffPlan(p) {
def speed(x: Int) = p.copy(
monthlyLimits = p.monthlyLimits.copy(
bandwidth = x)
)
}
((100.hrn).montly(1.gb) speed 100).excess ((2.hrn).per(1.gb))
((100.hrn).montly(1.gb).speed(100)).excess ((2.hrn).per(1.gb))
DSL: (100 hrn) montly (1 gb) speed 100 excess ((2 hrn) per (1 gb))
Internal
External
Need some boilerplate code.
Useful when developers need fluent business
domain object notation.
Internally - combination of builder and interpreter patterns
Useful when external users (non-developers) want to describe
domain objects.
Internally - language-mini-interpreter.
// [scala default library include parser combinators]
Post-OOD domain modelling
Domain Data Objects
‘OO’ Objects with behavior
• Closed world.
• Different lifecycle can be described by
different types
• Composition over inheritance
Domain Services
• Open world.
• No data, only functionality. Calls can be replayed.
• Traditional inheritance
Infrastructure Services
• Interpreters of ‘domain services’ functions
// phantom types.
Thanks for attention.
Fully - implemented ‘tiny’ domain model and DSL:
https://github.com/rssh/scala-training-materials/tree/master/fwdays2015-examples/
Ruslan Shevchenko
Lynx Capital Partners
https://github.com/rssh
@rssh1

More Related Content

Similar to Behind OOD: domain modelling in post-OO world.

"После OOD: как моделировать предметную область в пост-объектном мире" Руслан...
"После OOD: как моделировать предметную область в пост-объектном мире" Руслан..."После OOD: как моделировать предметную область в пост-объектном мире" Руслан...
"После OOD: как моделировать предметную область в пост-объектном мире" Руслан...
Fwdays
 
Visual basic intoduction
Visual basic intoductionVisual basic intoduction
Visual basic intoduction
Spy Seat
 
Programming Languages: some news for the last N years
Programming Languages: some news for the last N yearsProgramming Languages: some news for the last N years
Programming Languages: some news for the last N years
Ruslan Shevchenko
 
[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features
[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features
[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features
Andrew Liu
 
MongoDB Stich Overview
MongoDB Stich OverviewMongoDB Stich Overview
MongoDB Stich Overview
MongoDB
 
The Yin and Yang of Software
The Yin and Yang of SoftwareThe Yin and Yang of Software
The Yin and Yang of Software
elliando dias
 
Strata Software Architecture NY: The Data Dichotomy
Strata Software Architecture NY: The Data DichotomyStrata Software Architecture NY: The Data Dichotomy
Strata Software Architecture NY: The Data Dichotomy
Ben Stopford
 
Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...
Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...
Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...
confluent
 
Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...
Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...
Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...
Data Con LA
 
Dubbo and Weidian's practice on micro-service architecture
Dubbo and Weidian's practice on micro-service architectureDubbo and Weidian's practice on micro-service architecture
Dubbo and Weidian's practice on micro-service architecture
Huxing Zhang
 
Scaling DDS to Millions of Computers and Devices
Scaling DDS to Millions of Computers and DevicesScaling DDS to Millions of Computers and Devices
Scaling DDS to Millions of Computers and Devices
Rick Warren
 
Reactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and RxReactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and Rx
Sumant Tambe
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Flink Forward
 
Developing Dynamic Reports for TMS Using Crystal Reports
Developing Dynamic Reports for TMS Using Crystal ReportsDeveloping Dynamic Reports for TMS Using Crystal Reports
Developing Dynamic Reports for TMS Using Crystal Reports
Chad Petrovay
 
Introducing MongoDB Stitch, Backend-as-a-Service from MongoDB
Introducing MongoDB Stitch, Backend-as-a-Service from MongoDBIntroducing MongoDB Stitch, Backend-as-a-Service from MongoDB
Introducing MongoDB Stitch, Backend-as-a-Service from MongoDB
MongoDB
 
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVMVoxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Manuel Bernhardt
 
The Data Dichotomy- Rethinking the Way We Treat Data and Services
The Data Dichotomy- Rethinking the Way We Treat Data and ServicesThe Data Dichotomy- Rethinking the Way We Treat Data and Services
The Data Dichotomy- Rethinking the Way We Treat Data and Services
confluent
 
Event Driven Services Part 1: The Data Dichotomy
Event Driven Services Part 1: The Data Dichotomy Event Driven Services Part 1: The Data Dichotomy
Event Driven Services Part 1: The Data Dichotomy
Ben Stopford
 
introduction to Windows Comunication Foundation
introduction to Windows Comunication Foundationintroduction to Windows Comunication Foundation
introduction to Windows Comunication Foundation
redaxe12
 
Crafted Design - Sandro Mancuso
Crafted Design - Sandro MancusoCrafted Design - Sandro Mancuso
Crafted Design - Sandro Mancuso
JAXLondon2014
 

Similar to Behind OOD: domain modelling in post-OO world. (20)

"После OOD: как моделировать предметную область в пост-объектном мире" Руслан...
"После OOD: как моделировать предметную область в пост-объектном мире" Руслан..."После OOD: как моделировать предметную область в пост-объектном мире" Руслан...
"После OOD: как моделировать предметную область в пост-объектном мире" Руслан...
 
Visual basic intoduction
Visual basic intoductionVisual basic intoduction
Visual basic intoduction
 
Programming Languages: some news for the last N years
Programming Languages: some news for the last N yearsProgramming Languages: some news for the last N years
Programming Languages: some news for the last N years
 
[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features
[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features
[PASS Summit 2016] Azure DocumentDB: A Deep Dive into Advanced Features
 
MongoDB Stich Overview
MongoDB Stich OverviewMongoDB Stich Overview
MongoDB Stich Overview
 
The Yin and Yang of Software
The Yin and Yang of SoftwareThe Yin and Yang of Software
The Yin and Yang of Software
 
Strata Software Architecture NY: The Data Dichotomy
Strata Software Architecture NY: The Data DichotomyStrata Software Architecture NY: The Data Dichotomy
Strata Software Architecture NY: The Data Dichotomy
 
Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...
Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...
Kafka Summit NYC 2017 - The Data Dichotomy: Rethinking Data and Services with...
 
Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...
Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...
Big Data Day LA 2016/ Data Science Track - Enabling Cross-Screen Advertising ...
 
Dubbo and Weidian's practice on micro-service architecture
Dubbo and Weidian's practice on micro-service architectureDubbo and Weidian's practice on micro-service architecture
Dubbo and Weidian's practice on micro-service architecture
 
Scaling DDS to Millions of Computers and Devices
Scaling DDS to Millions of Computers and DevicesScaling DDS to Millions of Computers and Devices
Scaling DDS to Millions of Computers and Devices
 
Reactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and RxReactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and Rx
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
 
Developing Dynamic Reports for TMS Using Crystal Reports
Developing Dynamic Reports for TMS Using Crystal ReportsDeveloping Dynamic Reports for TMS Using Crystal Reports
Developing Dynamic Reports for TMS Using Crystal Reports
 
Introducing MongoDB Stitch, Backend-as-a-Service from MongoDB
Introducing MongoDB Stitch, Backend-as-a-Service from MongoDBIntroducing MongoDB Stitch, Backend-as-a-Service from MongoDB
Introducing MongoDB Stitch, Backend-as-a-Service from MongoDB
 
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVMVoxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
 
The Data Dichotomy- Rethinking the Way We Treat Data and Services
The Data Dichotomy- Rethinking the Way We Treat Data and ServicesThe Data Dichotomy- Rethinking the Way We Treat Data and Services
The Data Dichotomy- Rethinking the Way We Treat Data and Services
 
Event Driven Services Part 1: The Data Dichotomy
Event Driven Services Part 1: The Data Dichotomy Event Driven Services Part 1: The Data Dichotomy
Event Driven Services Part 1: The Data Dichotomy
 
introduction to Windows Comunication Foundation
introduction to Windows Comunication Foundationintroduction to Windows Comunication Foundation
introduction to Windows Comunication Foundation
 
Crafted Design - Sandro Mancuso
Crafted Design - Sandro MancusoCrafted Design - Sandro Mancuso
Crafted Design - Sandro Mancuso
 

More from Ruslan Shevchenko

Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Ruslan Shevchenko
 
Svitla talks 2021_03_25
Svitla talks 2021_03_25Svitla talks 2021_03_25
Svitla talks 2021_03_25
Ruslan Shevchenko
 
Akka / Lts behavior
Akka / Lts behaviorAkka / Lts behavior
Akka / Lts behavior
Ruslan Shevchenko
 
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Papers We Love / Kyiv :  PAXOS (and little about other consensuses )Papers We Love / Kyiv :  PAXOS (and little about other consensuses )
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Ruslan Shevchenko
 
Scala / Technology evolution
Scala  / Technology evolutionScala  / Technology evolution
Scala / Technology evolution
Ruslan Shevchenko
 
{co/contr} variance from LSP
{co/contr} variance  from LSP{co/contr} variance  from LSP
{co/contr} variance from LSP
Ruslan Shevchenko
 
N flavors of streaming
N flavors of streamingN flavors of streaming
N flavors of streaming
Ruslan Shevchenko
 
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Ruslan Shevchenko
 
SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.
Ruslan Shevchenko
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scala
Ruslan Shevchenko
 
Why scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with thisWhy scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with this
Ruslan Shevchenko
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
Ruslan Shevchenko
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applications
Ruslan Shevchenko
 
Csp scala wixmeetup2016
Csp scala wixmeetup2016Csp scala wixmeetup2016
Csp scala wixmeetup2016
Ruslan Shevchenko
 
IDLs
IDLsIDLs
R ext world/ useR! Kiev
R ext world/ useR!  KievR ext world/ useR!  Kiev
R ext world/ useR! Kiev
Ruslan Shevchenko
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platform
Ruslan Shevchenko
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
Ruslan Shevchenko
 
Web architecture - overview of techniques.
Web architecture - overview of  techniques.Web architecture - overview of  techniques.
Web architecture - overview of techniques.
Ruslan Shevchenko
 
R scala 17_05_2014
R scala 17_05_2014R scala 17_05_2014
R scala 17_05_2014
Ruslan Shevchenko
 

More from Ruslan Shevchenko (20)

Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
 
Svitla talks 2021_03_25
Svitla talks 2021_03_25Svitla talks 2021_03_25
Svitla talks 2021_03_25
 
Akka / Lts behavior
Akka / Lts behaviorAkka / Lts behavior
Akka / Lts behavior
 
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Papers We Love / Kyiv :  PAXOS (and little about other consensuses )Papers We Love / Kyiv :  PAXOS (and little about other consensuses )
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
 
Scala / Technology evolution
Scala  / Technology evolutionScala  / Technology evolution
Scala / Technology evolution
 
{co/contr} variance from LSP
{co/contr} variance  from LSP{co/contr} variance  from LSP
{co/contr} variance from LSP
 
N flavors of streaming
N flavors of streamingN flavors of streaming
N flavors of streaming
 
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
 
SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scala
 
Why scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with thisWhy scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with this
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applications
 
Csp scala wixmeetup2016
Csp scala wixmeetup2016Csp scala wixmeetup2016
Csp scala wixmeetup2016
 
IDLs
IDLsIDLs
IDLs
 
R ext world/ useR! Kiev
R ext world/ useR!  KievR ext world/ useR!  Kiev
R ext world/ useR! Kiev
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platform
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
 
Web architecture - overview of techniques.
Web architecture - overview of  techniques.Web architecture - overview of  techniques.
Web architecture - overview of techniques.
 
R scala 17_05_2014
R scala 17_05_2014R scala 17_05_2014
R scala 17_05_2014
 

Recently uploaded

DDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systemsDDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systems
Gerardo Pardo-Castellote
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Undress Baby
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
Peter Muessig
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
mz5nrf0n
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 

Recently uploaded (20)

DDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systemsDDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systems
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 

Behind OOD: domain modelling in post-OO world.

  • 1. Behind OOD // domain modelling in a post-OO world Ruslan Shevchenko Lynx Capital Partners https://github.com/rssh @rssh1
  • 2. Domain modelling • Representation of business domain objects: • in ‘head’ of people • in code
  • 3. Domain modelling. • Outline typical OOD issues • Build • simple domain model for toy billing system. // scala, can be mapped to java. • internal DSL
  • 4. Domain modelling • Traditional OO way: have layer of classes, which corresponds to domain objects. • Extensibility via inheritance in some consistent Universal Ontology • Intensional Equality [identity != attribute] • Object instance <=> Entity in real world
  • 5. Traditional OO WAY • Human is an upright, featherless biped with broad, flat nails.
  • 6. Traditional OO WAY • Human is an upright, featherless biped with broad, flat nails. Open for extensions close for modifications
  • 7. Traditional OO WAY • Human is an upright, featherless biped with broad, flat nails. Open for extensions close for modifications
  • 8. Traditional OO WAY • Intensional Equality [ mutability ] // same identity thought lifecycle
  • 9. Traditional OO WAY • Object in code <=> Object in real world class Person { int getId(); String getName(); int getAge(); Set<Person> getChilds() } — thread-safe ? — persistent updates ?
  • 10. Domain modelling • Traditional OO way: have layer of classes, which corresponds to domain objects. • Extensibility via inheritance in some consistent Universal Ontology • Intensional Equality [identity != attribute] • Object instance <=> Entity in real world
  • 11. Domain modelling • Traditional OO way: similar to early philosophy • Very general • Idealistic • Fit to concrete cases may be undefined
  • 12. Domain modelling • Post OO way: describe limited set of objects and relationships. • Algebra instead Ontology • Existential equality [identity == same attributes] • Rules of algebra <=> rules of reality.
  • 13. Domain modelling: where to start. • Example: description of small billing system Subscriber Billing System Service PaymentPlanuse in accordance with Service is Internet | Telephony PaymentPlan is Monthly Fee for Quantity Limit and Overhead cost per Unit Unit Internet is Gbin Telephony is Minute and Bandwidth
  • 14. TariffPlan: Use limit and quantity from service. sealed trait Service { type Limits def quantity(l:Limits): BigDecimal } case object Internet extends Service { case class Limits(gb:Int,bandwidth:Int) def quantity(l:Limits) = l.gb } case object Telephony extends Service { type Limits = Int def quantity(l) = l
  • 15. TariffPlan: Price per limit and charge case class TariffPlan[Limits]( monthlyFee: BigDecimal, monthlyLimits: Limits, excessCharge: BigDecimal )
  • 16. Subscriber ? Service ? case class Subscriber( id, name, … ) trait BillingService { def checkServiceAccess(u:Subscriber,s:Service):Boolean def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber def ratePeriod(u:Subscriber, date: DateTime) def acceptPayment(u:Subscriber, payment: Payment) } // Aggregate // let’s add to Subscriber all fields, what needed.
  • 17. adding fields for Subscriber aggregates. case class Subscriber(id, name, serviceInfos:Map[Service,SubscriberServiceInfo], account: BigDecimal, ….. ) case class SubscriberServiceInfo[S<:Service,L<:S#Limits]( service: S, tariffPlan: tariffPlan[S,L], amountUsed:Double ) trait BillingService { def checkServiceAccess(u:Subscriber,s:Service):Boolean = u.serviceInfos(s).isDefined && u.account > 0 }
  • 18. adding fields for Subscriber aggregates. case class Subscriber(id, name, serviceInfos:Map[Service,SubscriberServiceInfo[_,_]], account: BigDecimal, ….. ) case class ServiceUsage(service, amount, when) trait BillingService { def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber = serviceInfo(r.service) match { case Some(SubscriberServiceInfo(service,plan,amount)) => val price = …. u.copy(account = u.account - price, serviceInfo = serviceInfo.updated(s, }
  • 19. adding fields for Subscriber aggregates. trait BillingService { def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber = serviceInfo(r.service) match { case Some(SubscriberServiceInfo(service,plan,amount)) => val price = …. u.copy(account = u.account - price, serviceInfo = serviceInfo.updated(s, ServiceInfo(service,plan,amount+r.amount)) ) case None => throw new IllegalStateException(“service is not enabled”) } ……………. }
  • 20. Subscriber aggregates [rate: lastPayedDate] case class Subscriber(id, name, serviceInfos:Map[Service,SubscriberServiceInfo[_,_]], account: BigDecimal, lastPayedDate: DateTime ) trait BillingService { def ratePeriod(u:Subscriber,date:DateTime):Subscriber = if (date < u.lastPayedDate) u else { val price = ….. subscriber.copy(account = u.account - price, lastPayedDate = date+1.month) } }
  • 21. Subscriber: case class Subscriber( id : Long, name: String, serviceInfos:Map[Service,SubscriberServiceInfo[_,_]], account: BigDecimal, lastPayedDate: DateTime ) case class SubscriberServiceInfo[S<:Service,L<:S#Limits]( service: S, tariffPlan: tariffPlan[L], amountUsed:Double )
  • 22. Subscriber: case class Subscriber( id : Long, name: String, internetServiceInfo: ServiceInfo[Internet,Internet.Limits], telephonyServiceInfo: ServiceInfo[Telephony,Telephony.Limits], account: BigDecimal, lastPayedDate: DateTime ) { def serviceInfo(s:Service):SubscriberServiceInfo[s.type,s.Limits] = …. def updateServiceInfo[S<:Service,L<:S#Limits]( serviceInfo:SubscriberServiceInfo[S,L]): Subscriber = … }
  • 23. From domain model to implementation. [S1] Subscriber Service TariffPlan Domain Data/ Aggregates Services SubscriberOperations TariffPlanOperations …. Repository DD — contains only essential data Services — only functionality Testable. No mess with implementation. Service calls — domain events
  • 24. From domain model to implementation. [S1] Improvements/Refactoring space: • Errors handling • Deaggregate • Fluent DSL
  • 25. Errors handling (design for failure) trait BillingService { def checkServiceAccess(u:Subscriber,s:Service):Boolean def rateServiceUsage(u:Subscriber,r:ServiceUsage):Subscriber def ratePeriod(u:Subscriber, date: DateTime): Subscriber def acceptPayment(u:Subscriber, payment:Payment):Subscriber }
  • 26. Design for failure: trait BillingService { def checkServiceAccess(u:Subscriber,s:Service): Boolean def rateServiceUsage(u:Subscriber,r:ServiceUsage):Try[Subscriber] def ratePeriod(u:Subscriber, date: DateTime): Try[Subscriber] def acceptPayment(u:Subscriber, payment:Payment): Subscriber }
  • 27. Design for failure: sealed trait Try[+X] case class Success[X](v:X) extends Try[X] case class Failure(ex:Throwable) extends Try[Nothing] when use Try / traditional exception handling? Try — error recovery is a part of business layers. (i.e. errors is domain-related) Exception handling — error recovery is a part of infrastructure layer. (i. e. errors is system-related)
  • 28. Deaggregation: trait Repository { def create[T](): T def find[T](id: Id[T]): Try[T] def save[T](obj: T): Try[Boolean] }
  • 29. Deaggregation: trait Repository { def create[T](): T def find[T](id: Id[T]): Try[T] def save[T](obj: T) : Try[T] ……….. def subscriberServiceInfo[S<:Service,L<:S#Limits] (id: Id[Subscriber], s:S): SubscriberServiceInfo[S,L] def updateSubsriberServiceInfo[S<:Service,L<:S#Limits] ( id: Id[Subscriber],s:S,si:SubscriberServiceInfo[S,L]): Try[SubscriberServiceInfo[S,L]] }
  • 30. Deaggregation: trait BillingService { def checkServiceAccess(r:Repository, uid:Id[Subscriber], s:Service): Boolean def rateServiceUsage(r: Repository, uid:Id[Subscriber], r:ServiceUsage):Try[Subscriber] ….. }
  • 31. Deaggregation: trait BillingService { val repository: Repository def checkServiceAccess(uid:Id[Subscriber], s:Service): Try[Boolean] def rateServiceUsage(uid:Id[Subscriber], r:ServiceUsage):Try[Subscriber] ….. } // BillingService operations interpret repository
  • 32. Deaggregation. [S2] Subscriber Service TariffPlan Domain Data/ Aggregates Services SubscriberOperations TariffPlanOperations …. Repository Interpret - Not for all cases - Loss - generality of repository - simply logic - Gain - simple repository operations - more efficient data access.
  • 33. DSL: Domain Specific Language. Idea: fluent syntax for fluent operations. • Syntax sugar, can be used by non-programmers • ‘Micro-interpreter/compiler’ • Internal/External Let’s build simple Internal DSL for our tariff plans.
  • 34. TariffPlan: DSL case class TariffPlan[Limits]( monthlyFee: BigDecimal, monthlyLimits: Limits, excessCharge: BigDecimal ) TariffPlan(100,Limits(1,100),2) TariffPlan(montlyFee=100, Internet.Limits(gb=1,bandwidth=100), 2) 100 hrn montly (1 gb) speed 100 excess 2 hrn per 1 gb // let’s build
  • 35. TariffPlan: DSL (100 hrn) montly (1 gb) speed 100 excess (2 hrn) per (1 gb) trait TariffPlanDSL[S <: Service, L <: S#Limits] { implicit class ToHrn(v: Int) { def hrn = this def monthly(x: LimitExpression) = TariffPlan(v, x.limit, 0) def per(x: QuantityExpression } 1 hrn = 1.hrn = new ToHrn(1).hrn trait LimitExpression{ def limit: L } type QuantityExpression { def quantity: Int }
  • 36. TariffPlan: DSL (100 hrn) montly (1 gb) speed 100 excess (2 hrn) per (1 gb) object InternetTariffPlanDSL extends TariffPlanDSL[Internet.type, Internet.Limits] implicit class Gb(v: Int) extends LimitExpression with QuantityExpression{ def gb = this def limit = Internet.Limits(v,100) def quantity = x }
  • 37. TariffPlan: DSL (100 hrn) montly (1 gb) speed 100 excess (2 hrn) per (1 gb) (100 hrn) montly (1 gb) == (100.hrn).montly(1.gb)
  • 38. TariffPlan: DSL (100 hrn) montly (1 gb) speed 100 excess ((2 hrn) per (1 gb)) trait TariffPlanDSL[S,L] case class PerExpression(money: ToHrn, quantity: QuantityExpression) trait RichTariffPlan(p: TariffPlan[L]) { def excess(x: PerExpression) = p.copy(excessCost=x.v) } ((100.hrn).montly(1.gb) speed 100).excess((2 hrn) per (1 gb))
  • 39. TariffPlan: DSL (100 hrn) montly (1 gb) speed 100 excess ((2 hrn) per (1 gb)) object InternetTariffPlanDSL[S,L] trait RichTariffPlan(p: TariffPlan[L]) extends super.RichTariffPlan(p) { def speed(x: Int) = p.copy( monthlyLimits = p.monthlyLimits.copy( bandwidth = x) ) } ((100.hrn).montly(1.gb) speed 100).excess ((2.hrn).per(1.gb)) ((100.hrn).montly(1.gb).speed(100)).excess ((2.hrn).per(1.gb))
  • 40. DSL: (100 hrn) montly (1 gb) speed 100 excess ((2 hrn) per (1 gb)) Internal External Need some boilerplate code. Useful when developers need fluent business domain object notation. Internally - combination of builder and interpreter patterns Useful when external users (non-developers) want to describe domain objects. Internally - language-mini-interpreter. // [scala default library include parser combinators]
  • 41. Post-OOD domain modelling Domain Data Objects ‘OO’ Objects with behavior • Closed world. • Different lifecycle can be described by different types • Composition over inheritance Domain Services • Open world. • No data, only functionality. Calls can be replayed. • Traditional inheritance Infrastructure Services • Interpreters of ‘domain services’ functions // phantom types.
  • 42. Thanks for attention. Fully - implemented ‘tiny’ domain model and DSL: https://github.com/rssh/scala-training-materials/tree/master/fwdays2015-examples/ Ruslan Shevchenko Lynx Capital Partners https://github.com/rssh @rssh1