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
• 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
• 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 system of
relationship and provide implementation
• Algebra instead Ontology
• Existential equality [identity == same
attributes]
• Elements/Services instead Objects.
Domain modelling
• Post OO way: describe limited system of
relationship and provide implementation
• Algebra instead Ontology
• Existential equality [identity == same
attributes]
• Elements/Services instead Objects.
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)
}
// 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”)
}
…………….
}
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
)
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:
• Design for failure
• Deaggregate
• Fluent DSL
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[Unit]
………..
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[Unit]
}
Deaggregation:
trait BillingService
{
def checkServiceAccess(r:Repository, uid:Id[Subscriber],
s:Service): Try[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
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 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))
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)
}
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)
)
}
DSL
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
Immutable 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

What's hot

BigQuery case study in Groovenauts & Dive into the DataflowJavaSDK
BigQuery case study in Groovenauts & Dive into the DataflowJavaSDKBigQuery case study in Groovenauts & Dive into the DataflowJavaSDK
BigQuery case study in Groovenauts & Dive into the DataflowJavaSDK
nagachika t
 
Python and MongoDB as a Market Data Platform by James Blackburn
Python and MongoDB as a Market Data Platform by James BlackburnPython and MongoDB as a Market Data Platform by James Blackburn
Python and MongoDB as a Market Data Platform by James Blackburn
PyData
 
Streaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka StreamsStreaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka Streams
vito jeng
 
Uber Real Time Data Analytics
Uber Real Time Data AnalyticsUber Real Time Data Analytics
Uber Real Time Data Analytics
Ankur Bansal
 
Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...
Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...
Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...
confluent
 
How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...
How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...
How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...
StreamNative
 
RabbitMQ + OpenLDAP
RabbitMQ + OpenLDAPRabbitMQ + OpenLDAP
RabbitMQ + OpenLDAP
Cheng Hsien Chen
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Matt Stubbs
 
Spark (Structured) Streaming vs. Kafka Streams
Spark (Structured) Streaming vs. Kafka StreamsSpark (Structured) Streaming vs. Kafka Streams
Spark (Structured) Streaming vs. Kafka Streams
Guido Schmutz
 
Store stream data on Data Lake
Store stream data on Data LakeStore stream data on Data Lake
Store stream data on Data Lake
Marcos Rebelo
 
MongoDB Tick Data Presentation
MongoDB Tick Data PresentationMongoDB Tick Data Presentation
MongoDB Tick Data PresentationMongoDB
 
Orion Context Broker 1.15.0
Orion Context Broker 1.15.0Orion Context Broker 1.15.0
Orion Context Broker 1.15.0
Fermin Galan
 
Transforming Mobile Push Notifications with Big Data
Transforming Mobile Push Notifications with Big DataTransforming Mobile Push Notifications with Big Data
Transforming Mobile Push Notifications with Big Data
plumbee
 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache KafkaSolutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Guido Schmutz
 
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Guido Schmutz
 
Linux AD integration with OpenDJ
Linux AD integration with OpenDJLinux AD integration with OpenDJ
Linux AD integration with OpenDJ
Pieter Baele
 
How to build an ETL pipeline with Apache Beam on Google Cloud Dataflow
How to build an ETL pipeline with Apache Beam on Google Cloud DataflowHow to build an ETL pipeline with Apache Beam on Google Cloud Dataflow
How to build an ETL pipeline with Apache Beam on Google Cloud Dataflow
Lucas Arruda
 
Lambda Architecture Using SQL
Lambda Architecture Using SQLLambda Architecture Using SQL
Lambda Architecture Using SQL
SATOSHI TAGOMORI
 
Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...
Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...
Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...
confluent
 
ApacheCon BigData Europe 2015
ApacheCon BigData Europe 2015 ApacheCon BigData Europe 2015
ApacheCon BigData Europe 2015
Renato Javier Marroquín Mogrovejo
 

What's hot (20)

BigQuery case study in Groovenauts & Dive into the DataflowJavaSDK
BigQuery case study in Groovenauts & Dive into the DataflowJavaSDKBigQuery case study in Groovenauts & Dive into the DataflowJavaSDK
BigQuery case study in Groovenauts & Dive into the DataflowJavaSDK
 
Python and MongoDB as a Market Data Platform by James Blackburn
Python and MongoDB as a Market Data Platform by James BlackburnPython and MongoDB as a Market Data Platform by James Blackburn
Python and MongoDB as a Market Data Platform by James Blackburn
 
Streaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka StreamsStreaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka Streams
 
Uber Real Time Data Analytics
Uber Real Time Data AnalyticsUber Real Time Data Analytics
Uber Real Time Data Analytics
 
Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...
Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...
Closing the Loop in Extended Reality with Kafka Streams and Machine Learning ...
 
How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...
How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...
How Pulsar Enables Netdata to Offer Unlimited Infrastructure Monitoring for F...
 
RabbitMQ + OpenLDAP
RabbitMQ + OpenLDAPRabbitMQ + OpenLDAP
RabbitMQ + OpenLDAP
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
 
Spark (Structured) Streaming vs. Kafka Streams
Spark (Structured) Streaming vs. Kafka StreamsSpark (Structured) Streaming vs. Kafka Streams
Spark (Structured) Streaming vs. Kafka Streams
 
Store stream data on Data Lake
Store stream data on Data LakeStore stream data on Data Lake
Store stream data on Data Lake
 
MongoDB Tick Data Presentation
MongoDB Tick Data PresentationMongoDB Tick Data Presentation
MongoDB Tick Data Presentation
 
Orion Context Broker 1.15.0
Orion Context Broker 1.15.0Orion Context Broker 1.15.0
Orion Context Broker 1.15.0
 
Transforming Mobile Push Notifications with Big Data
Transforming Mobile Push Notifications with Big DataTransforming Mobile Push Notifications with Big Data
Transforming Mobile Push Notifications with Big Data
 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache KafkaSolutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
 
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
Spark (Structured) Streaming vs. Kafka Streams - two stream processing platfo...
 
Linux AD integration with OpenDJ
Linux AD integration with OpenDJLinux AD integration with OpenDJ
Linux AD integration with OpenDJ
 
How to build an ETL pipeline with Apache Beam on Google Cloud Dataflow
How to build an ETL pipeline with Apache Beam on Google Cloud DataflowHow to build an ETL pipeline with Apache Beam on Google Cloud Dataflow
How to build an ETL pipeline with Apache Beam on Google Cloud Dataflow
 
Lambda Architecture Using SQL
Lambda Architecture Using SQLLambda Architecture Using SQL
Lambda Architecture Using SQL
 
Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...
Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...
Data-Oriented Programming with Clojure and Jackdaw (Charles Reese, Funding Ci...
 
ApacheCon BigData Europe 2015
ApacheCon BigData Europe 2015 ApacheCon BigData Europe 2015
ApacheCon BigData Europe 2015
 

Viewers also liked

Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"
Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"
Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"
Fwdays
 
Скрам и Канбан: применимость самых распространенных методов организации умств...
Скрам и Канбан: применимость самых распространенных методов организации умств...Скрам и Канбан: применимость самых распространенных методов организации умств...
Скрам и Канбан: применимость самых распространенных методов организации умств...
Fwdays
 
Трансформация команды: от инди разработки к играм с коммерческой успешностью
Трансформация команды: от инди разработки к играм с коммерческой успешностьюТрансформация команды: от инди разработки к играм с коммерческой успешностью
Трансформация команды: от инди разработки к играм с коммерческой успешностью
Fwdays
 
Евгений Обрезков "Behind the terminal"
Евгений Обрезков "Behind the terminal"Евгений Обрезков "Behind the terminal"
Евгений Обрезков "Behind the terminal"
Fwdays
 
Lightweight APIs in mRuby (Михаил Бортник)
Lightweight APIs in mRuby (Михаил Бортник)Lightweight APIs in mRuby (Михаил Бортник)
Lightweight APIs in mRuby (Михаил Бортник)
Fwdays
 
4 puchnina.pptx
4 puchnina.pptx4 puchnina.pptx
4 puchnina.pptxFwdays
 
Анатолий Попель: "Формы оплаты и платёжные шлюзы"
Анатолий Попель: "Формы оплаты и платёжные шлюзы"Анатолий Попель: "Формы оплаты и платёжные шлюзы"
Анатолий Попель: "Формы оплаты и платёжные шлюзы"
Fwdays
 
Швейцарія, масштабування Scrum і розподілені команди от Романа Сахарова
Швейцарія, масштабування Scrum і розподілені команди от Романа СахароваШвейцарія, масштабування Scrum і розподілені команди от Романа Сахарова
Швейцарія, масштабування Scrum і розподілені команди от Романа Сахарова
Fwdays
 
Designing for Privacy
Designing for PrivacyDesigning for Privacy
Designing for Privacy
exultantwarning51
 
"Красная книга веб-разработчика" Виктор Полищук
"Красная книга веб-разработчика" Виктор Полищук"Красная книга веб-разработчика" Виктор Полищук
"Красная книга веб-разработчика" Виктор Полищук
Fwdays
 
Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...
Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...
Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...
Fwdays
 
Илья Прукко: "Как дизайнеру не становиться художником"
Илья Прукко: "Как дизайнеру не становиться художником"Илья Прукко: "Как дизайнеру не становиться художником"
Илья Прукко: "Как дизайнеру не становиться художником"
Fwdays
 
"Query Execution: Expectation - Reality (Level 300)" Денис Резник
"Query Execution: Expectation - Reality (Level 300)" Денис Резник"Query Execution: Expectation - Reality (Level 300)" Денис Резник
"Query Execution: Expectation - Reality (Level 300)" Денис Резник
Fwdays
 
Евгений Жарков AngularJS: Good parts
Евгений Жарков AngularJS: Good partsЕвгений Жарков AngularJS: Good parts
Евгений Жарков AngularJS: Good parts
Fwdays
 
Светлана Старикова "Building a self-managing team: why you should not have e...
 Светлана Старикова "Building a self-managing team: why you should not have e... Светлана Старикова "Building a self-managing team: why you should not have e...
Светлана Старикова "Building a self-managing team: why you should not have e...
Fwdays
 
Michael North "The Road to Native Web Components"
Michael North "The Road to Native Web Components"Michael North "The Road to Native Web Components"
Michael North "The Road to Native Web Components"
Fwdays
 
"Frameworks in 2015" Андрей Листочкин
"Frameworks in 2015" Андрей Листочкин"Frameworks in 2015" Андрей Листочкин
"Frameworks in 2015" Андрей Листочкин
Fwdays
 
"Spring Boot. Boot up your development" Сергей Моренец
"Spring Boot. Boot up your development" Сергей Моренец"Spring Boot. Boot up your development" Сергей Моренец
"Spring Boot. Boot up your development" Сергей Моренец
Fwdays
 
Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений"
Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений" Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений"
Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений"
Fwdays
 
Сергей Жук "Android Performance Tips & Tricks"
Сергей Жук "Android Performance Tips & Tricks"Сергей Жук "Android Performance Tips & Tricks"
Сергей Жук "Android Performance Tips & Tricks"
Fwdays
 

Viewers also liked (20)

Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"
Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"
Анастасия Войтова: "Building profanity filters on mobile: clbuttic sh!t"
 
Скрам и Канбан: применимость самых распространенных методов организации умств...
Скрам и Канбан: применимость самых распространенных методов организации умств...Скрам и Канбан: применимость самых распространенных методов организации умств...
Скрам и Канбан: применимость самых распространенных методов организации умств...
 
Трансформация команды: от инди разработки к играм с коммерческой успешностью
Трансформация команды: от инди разработки к играм с коммерческой успешностьюТрансформация команды: от инди разработки к играм с коммерческой успешностью
Трансформация команды: от инди разработки к играм с коммерческой успешностью
 
Евгений Обрезков "Behind the terminal"
Евгений Обрезков "Behind the terminal"Евгений Обрезков "Behind the terminal"
Евгений Обрезков "Behind the terminal"
 
Lightweight APIs in mRuby (Михаил Бортник)
Lightweight APIs in mRuby (Михаил Бортник)Lightweight APIs in mRuby (Михаил Бортник)
Lightweight APIs in mRuby (Михаил Бортник)
 
4 puchnina.pptx
4 puchnina.pptx4 puchnina.pptx
4 puchnina.pptx
 
Анатолий Попель: "Формы оплаты и платёжные шлюзы"
Анатолий Попель: "Формы оплаты и платёжные шлюзы"Анатолий Попель: "Формы оплаты и платёжные шлюзы"
Анатолий Попель: "Формы оплаты и платёжные шлюзы"
 
Швейцарія, масштабування Scrum і розподілені команди от Романа Сахарова
Швейцарія, масштабування Scrum і розподілені команди от Романа СахароваШвейцарія, масштабування Scrum і розподілені команди от Романа Сахарова
Швейцарія, масштабування Scrum і розподілені команди от Романа Сахарова
 
Designing for Privacy
Designing for PrivacyDesigning for Privacy
Designing for Privacy
 
"Красная книга веб-разработчика" Виктор Полищук
"Красная книга веб-разработчика" Виктор Полищук"Красная книга веб-разработчика" Виктор Полищук
"Красная книга веб-разработчика" Виктор Полищук
 
Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...
Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...
Алексей Рыбаков: "Wearable OS год спустя: Apple Watch 2.0, Android Wear 5.1.1...
 
Илья Прукко: "Как дизайнеру не становиться художником"
Илья Прукко: "Как дизайнеру не становиться художником"Илья Прукко: "Как дизайнеру не становиться художником"
Илья Прукко: "Как дизайнеру не становиться художником"
 
"Query Execution: Expectation - Reality (Level 300)" Денис Резник
"Query Execution: Expectation - Reality (Level 300)" Денис Резник"Query Execution: Expectation - Reality (Level 300)" Денис Резник
"Query Execution: Expectation - Reality (Level 300)" Денис Резник
 
Евгений Жарков AngularJS: Good parts
Евгений Жарков AngularJS: Good partsЕвгений Жарков AngularJS: Good parts
Евгений Жарков AngularJS: Good parts
 
Светлана Старикова "Building a self-managing team: why you should not have e...
 Светлана Старикова "Building a self-managing team: why you should not have e... Светлана Старикова "Building a self-managing team: why you should not have e...
Светлана Старикова "Building a self-managing team: why you should not have e...
 
Michael North "The Road to Native Web Components"
Michael North "The Road to Native Web Components"Michael North "The Road to Native Web Components"
Michael North "The Road to Native Web Components"
 
"Frameworks in 2015" Андрей Листочкин
"Frameworks in 2015" Андрей Листочкин"Frameworks in 2015" Андрей Листочкин
"Frameworks in 2015" Андрей Листочкин
 
"Spring Boot. Boot up your development" Сергей Моренец
"Spring Boot. Boot up your development" Сергей Моренец"Spring Boot. Boot up your development" Сергей Моренец
"Spring Boot. Boot up your development" Сергей Моренец
 
Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений"
Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений" Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений"
Александр Махомет "Feature Flags. Уменьшаем риски при выпуске изменений"
 
Сергей Жук "Android Performance Tips & Tricks"
Сергей Жук "Android Performance Tips & Tricks"Сергей Жук "Android Performance Tips & Tricks"
Сергей Жук "Android Performance Tips & Tricks"
 

Similar to "После OOD: как моделировать предметную область в пост-объектном мире" Руслан Шевченко

Behind OOD: domain modelling in post-OO world.
Behind OOD:  domain modelling in post-OO world.Behind OOD:  domain modelling in post-OO world.
Behind OOD: domain modelling in post-OO world.
Ruslan Shevchenko
 
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
 
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
 
Types Working for You, Not Against You
Types Working for You, Not Against YouTypes Working for You, Not Against You
Types Working for You, Not Against You
C4Media
 
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
 
MongoDB Stich Overview
MongoDB Stich OverviewMongoDB Stich Overview
MongoDB Stich Overview
MongoDB
 
Data Pipeline at Tapad
Data Pipeline at TapadData Pipeline at Tapad
Data Pipeline at Tapad
Toby Matejovsky
 
Hypermedia System Architecture for a Web of Things
Hypermedia System Architecture for a Web of ThingsHypermedia System Architecture for a Web of Things
Hypermedia System Architecture for a Web of Things
Michael Koster
 
INTEGRATE 2022 - Data Mapping in the Microsoft Cloud
INTEGRATE 2022 - Data Mapping in the Microsoft CloudINTEGRATE 2022 - Data Mapping in the Microsoft Cloud
INTEGRATE 2022 - Data Mapping in the Microsoft Cloud
Daniel Toomey
 
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
 
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
 
introduction to Windows Comunication Foundation
introduction to Windows Comunication Foundationintroduction to Windows Comunication Foundation
introduction to Windows Comunication Foundation
redaxe12
 
TWYP - An event driven architecture in a fast growing ecosystem
TWYP - An event driven architecture in a fast growing ecosystemTWYP - An event driven architecture in a fast growing ecosystem
TWYP - An event driven architecture in a fast growing ecosystem
Sander de Groot
 
Norikra: SQL Stream Processing In Ruby
Norikra: SQL Stream Processing In RubyNorikra: SQL Stream Processing In Ruby
Norikra: SQL Stream Processing In Ruby
SATOSHI TAGOMORI
 
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInventPros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
Sudhir Tonse
 
Async
AsyncAsync
Testing in the World of Functional Programming
Testing in the World of Functional ProgrammingTesting in the World of Functional Programming
Testing in the World of Functional Programming
Luka Jacobowitz
 
Service design om ppt @ DOMS
Service design om ppt @ DOMSService design om ppt @ DOMS
Service design om ppt @ DOMS
Babasab Patil
 
Spark streaming: Best Practices
Spark streaming: Best PracticesSpark streaming: Best Practices
Spark streaming: Best Practices
Prakash Chockalingam
 
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
 

Similar to "После OOD: как моделировать предметную область в пост-объектном мире" Руслан Шевченко (20)

Behind OOD: domain modelling in post-OO world.
Behind OOD:  domain modelling in post-OO world.Behind OOD:  domain modelling in post-OO world.
Behind OOD: domain modelling in post-OO world.
 
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 ...
 
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
 
Types Working for You, Not Against You
Types Working for You, Not Against YouTypes Working for You, Not Against You
Types Working for You, Not Against You
 
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 Stich Overview
MongoDB Stich OverviewMongoDB Stich Overview
MongoDB Stich Overview
 
Data Pipeline at Tapad
Data Pipeline at TapadData Pipeline at Tapad
Data Pipeline at Tapad
 
Hypermedia System Architecture for a Web of Things
Hypermedia System Architecture for a Web of ThingsHypermedia System Architecture for a Web of Things
Hypermedia System Architecture for a Web of Things
 
INTEGRATE 2022 - Data Mapping in the Microsoft Cloud
INTEGRATE 2022 - Data Mapping in the Microsoft CloudINTEGRATE 2022 - Data Mapping in the Microsoft Cloud
INTEGRATE 2022 - Data Mapping in the Microsoft Cloud
 
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
 
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
 
introduction to Windows Comunication Foundation
introduction to Windows Comunication Foundationintroduction to Windows Comunication Foundation
introduction to Windows Comunication Foundation
 
TWYP - An event driven architecture in a fast growing ecosystem
TWYP - An event driven architecture in a fast growing ecosystemTWYP - An event driven architecture in a fast growing ecosystem
TWYP - An event driven architecture in a fast growing ecosystem
 
Norikra: SQL Stream Processing In Ruby
Norikra: SQL Stream Processing In RubyNorikra: SQL Stream Processing In Ruby
Norikra: SQL Stream Processing In Ruby
 
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInventPros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
 
Async
AsyncAsync
Async
 
Testing in the World of Functional Programming
Testing in the World of Functional ProgrammingTesting in the World of Functional Programming
Testing in the World of Functional Programming
 
Service design om ppt @ DOMS
Service design om ppt @ DOMSService design om ppt @ DOMS
Service design om ppt @ DOMS
 
Spark streaming: Best Practices
Spark streaming: Best PracticesSpark streaming: Best Practices
Spark streaming: Best Practices
 
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 ...
 

More from Fwdays

"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh
Fwdays
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
Fwdays
 
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
Fwdays
 
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
Fwdays
 
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y..."How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
Fwdays
 
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
Fwdays
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
Fwdays
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
Fwdays
 
"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets
Fwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
Fwdays
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
Fwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
Fwdays
 
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
Fwdays
 
"Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl..."Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl...
Fwdays
 
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T..."How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
Fwdays
 
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ..."The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
Fwdays
 
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu..."[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
Fwdays
 
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care..."[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
Fwdays
 
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"..."4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
Fwdays
 

More from Fwdays (20)

"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh"What I learned through reverse engineering", Yuri Artiukh
"What I learned through reverse engineering", Yuri Artiukh
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov"Micro frontends: Unbelievably true life story", Dmytro Pavlov
"Micro frontends: Unbelievably true life story", Dmytro Pavlov
 
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
 
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
"JavaScript. Standard evolution, when nobody cares", Roman Savitskyi
 
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y..."How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
"How Preply reduced ML model development time from 1 month to 1 day",Yevhen Y...
 
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
"GenAI Apps: Our Journey from Ideas to Production Excellence",Danil Topchii
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets"What is a RAG system and how to build it",Dmytro Spodarets
"What is a RAG system and how to build it",Dmytro Spodarets
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi"Distributed graphs and microservices in Prom.ua",  Maksym Kindritskyi
"Distributed graphs and microservices in Prom.ua", Maksym Kindritskyi
 
"Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl..."Rethinking the existing data loading and processing process as an ETL exampl...
"Rethinking the existing data loading and processing process as an ETL exampl...
 
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T..."How Ukrainian IT specialist can go on vacation abroad without crossing the T...
"How Ukrainian IT specialist can go on vacation abroad without crossing the T...
 
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ..."The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
"The Strength of Being Vulnerable: the experience from CIA, Tesla and Uber", ...
 
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu..."[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
"[QUICK TALK] Radical candor: how to achieve results faster thanks to a cultu...
 
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care..."[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
"[QUICK TALK] PDP Plan, the only one door to raise your salary and boost care...
 
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"..."4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
"4 horsemen of the apocalypse of working relationships (+ antidotes to them)"...
 

Recently uploaded

The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
Jen Stirrup
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..
UiPathCommunity
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
Peter Spielvogel
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Vlad Stirbu
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
UiPathCommunity
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 

Recently uploaded (20)

The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 

"После OOD: как моделировать предметную область в пост-объектном мире" Руслан Шевченко

  • 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 • 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
  • 4. Traditional OO WAY • Human is an upright, featherless biped with broad, flat nails.
  • 5. Traditional OO WAY • Human is an upright, featherless biped with broad, flat nails. Open for extensions close for modifications
  • 6. Traditional OO WAY • Intensional Equality [ mutability ] // same identity thought lifecycle
  • 7. 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 ?
  • 8. 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
  • 9. Domain modelling • Traditional OO way: similar to early philosophy • Very general • Idealistic • Fit to concrete cases may be undefined
  • 10. Domain modelling • Post OO way: describe limited system of relationship and provide implementation • Algebra instead Ontology • Existential equality [identity == same attributes] • Elements/Services instead Objects.
  • 11. Domain modelling • Post OO way: describe limited system of relationship and provide implementation • Algebra instead Ontology • Existential equality [identity == same attributes] • Elements/Services instead Objects.
  • 12. 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
  • 13. 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
  • 14. TariffPlan: Price per limit and charge case class TariffPlan[Limits]( monthlyFee: BigDecimal, monthlyLimits: Limits, excessCharge: BigDecimal )
  • 15. 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) } // Aggregate // let’s add to Subscriber all fields, what needed.
  • 16. 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 }
  • 17. 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, }
  • 18. 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”) } ……………. }
  • 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 )
  • 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: • Design for failure • Deaggregate • Fluent DSL
  • 25. 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[Unit] ……….. 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[Unit] }
  • 30. Deaggregation: trait BillingService { def checkServiceAccess(r:Repository, uid:Id[Subscriber], s:Service): Try[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
  • 33. 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 per 1 gb // let’s build
  • 34. 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 }
  • 35. 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 }
  • 36. 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) }
  • 37. 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) ) }
  • 38. DSL 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]
  • 39. Post-OOD domain modelling Immutable 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.
  • 40. 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