SlideShare a Scribd company logo
Functional Programming
& Event Sourcing
A pair made in heaven
twitter: @rabbitonweb, email: paul.szulc@gmail.com
Functional Programming
● no assignment statements
● no assignment statements
● no variables
● no assignment statements
● no variables
● once given a value, never
change
● no assignment statements
● no variables
● once given a value, never
change
● no side-effects at all
● no assignment statements
● no variables
● once given a value, never
change
● no side-effects at all
“The functional programmer
sounds rather like a mediæval
monk,
“The functional programmer
sounds rather like a mediæval
monk, denying himself the
pleasures of life
“The functional programmer
sounds rather like a mediæval
monk, denying himself the
pleasures of life in the hope
that it will make him virtuous.”
Functional Programming
case class User(id: Long, fn: String, ln: String)
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
class UserFinder(cache: Cache, repo: UserRepo) {
}
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
class UserFinder(cache: Cache, repo: UserRepo) {
def findUser(id: Long): User = {
}
}
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
class UserFinder(cache: Cache, repo: UserRepo) {
def findUser(id: Long): User = {
val maybeUser: Option[User] = cache.check(id)
}
}
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
class UserFinder(cache: Cache, repo: UserRepo) {
def findUser(id: Long): User = {
val maybeUser: Option[User] = cache.check(id)
if (maybeUser.isDefined) {
maybeUser.get
}
}
}
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
class UserFinder(cache: Cache, repo: UserRepo) {
def findUser(id: Long): User = {
val maybeUser: Option[User] = cache.check(id)
if (maybeUser.isDefined) {
maybeUser.get
} else {
val user: User = repo.retrieve(id)
cache.insert(user.id, user)
}
}
}
No concept of ‘time’
f(input): output
input f(input): output
input f(input): output output
input f(input): output output g(input): output
input f(input): output output g(input): output output
input f(input): output output g(input): output output
h = g o f
input f(input): output output g(input): output output
Modularity & composition
h = g o f
input f(input): output output g(input): output output
/**
* This function returns a reversed list
* @param list A list to be reversed
* @return A reversed list
*/
public List<T> reverse(List<t> list) { ??? }
/**
* This function returns a reversed list
* @param list A list to be reversed
* @return A reversed list
*/
public List<T> reverse(List<t> list) { ??? }
/**
* This function returns a reversed list
* @param list A list to be reversed
public List<T> reverse(List<t> list) { ??? }
/**
* This function returns a reversed list
public List<T> reverse(List<t> list) { ??? }
/**
public List<T> reverse(List<t> list) { ??? }
public List<T> reverse(List<t> list) { ??? }
public List<T> reverse(List<t> list) {
return list.sort();
}
def smdfknmsdfp[A](a: A): A = ???
def smdfknmsdfp[A](a: A): A = a
def identity[A](a: A): A = a
def smdfknmsdfp[A](a: A): A = a
def smdfknmsdfp(a: Int): Int = ???
def smdfknmsdfp(a: Int): Int = a
= a + 10
= 10
“Why Functional Programming Matters”
J. Hughes
http://comjnl.oxfordjournals.org/content/32/2/98.
full.pdf
“Why Functional Programming Matters”
J. Hughes, Nov. 1988
http://comjnl.oxfordjournals.org/content/32/2/98.
full.pdf
Soft introduction
“Why Functional Programming Matters”
J. Hughes, Nov. 1988
http://comjnl.oxfordjournals.org/content/32/2/98.
full.pdf
“Program Design by Calculation”
J.N. Oliveira
http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
“Program Design by Calculation”
J.N. Oliveira, Draft
http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
Patterns in FP World
“Program Design by Calculation”
J.N. Oliveira, Draft
http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
Patterns in FP World Math Matters
“Program Design by Calculation”
J.N. Oliveira, Draft
http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
“A lengthy approach to Haskell fundamentals”
http://www.davesquared.net/2012/05/lengthy-
approach-to-haskell.html
Functional Programming
Functional Programming
How to do something
useful?
How to do something
useful?
case class User(id: Long, fn: String, ln: String)
class Cache { def check(id: Long): Option[User] = ??? }
case class UserRepo(cache: Cache) {
def retrieve(id: Long): User = ???
}
class UserFinder(cache: Cache, repo: UserRepo) {
def findUser(id: Long): User = {
val maybeUser: Option[User] = cache.check(id)
if (maybeUser.isDefined) {
maybeUser.get
} else {
val user: User = repo.retrieve(id)
cache.insert(user.id, user)
}
}
}
case class User(id: Long, fn: String, ln: String)
case class User(id: Long, fn: String, ln: String)
class Cache {}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
def findUser(id: Long)(cache: Cache): (Cache, User) = {
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
def findUser(id: Long)(cache: Cache): (Cache, User) = {
val (c, mu) = check(id)(cache)
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
def findUser(id: Long)(cache: Cache): (Cache, User) = {
val (c, mu) = check(id)(cache)
mu match {
case Some(u) => (c, u)
}
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
def findUser(id: Long)(cache: Cache): (Cache, User) = {
val (c, mu) = check(id)(cache)
mu match {
case Some(u) => (c, u)
case None => retrieve(id)(c)
}
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
def findUser(id: Long)(cache: Cache): (Cache, User) = {
val (c, mu) = check(id)(cache)
mu match {
case Some(u) => (c, u)
case None => retrieve(id)(c)
}
}
}
S => (S, A)
State[S, A]
S => (S, A)
State[S, A]
S => (S, A)
.run(S)
State[S, A]
S => (S, A)
.map(A => B): State[S, B]
State[S, A]
S => (S, A)
.flatMap(A => State[S, B]): State[S,B]
object State {
def apply[S, A] (f: S => (S,A)): State[S, A] =
}
object State {
def apply[S, A] (f: S => (S,A)): State[S, A] =
new State[S, A] {
def run(s: S) = f(s)
}
}
object State {
def apply[S, A] (f: S => (S,A)): State[S, A] =
new State[S, A] {
def run(s: S) = f(s)
}
}
def check(id: String) =
object State {
def apply[S, A] (f: S => (S,A)): State[S, A] =
new State[S, A] {
def run(s: S) = f(s)
}
}
def check(id: String) =
(c: Cache) => (c, c.get(id))
object State {
def apply[S, A] (f: S => (S,A)): State[S, A] =
new State[S, A] {
def run(s: S) = f(s)
}
}
def check(id: String) = State[Cache, Option[User]].apply {
(c: Cache) => (c, c.get(id))
}
object State {
def apply[S, A] (f: S => (S,A)): State[S, A] =
new State[S, A] {
def run(s: S) = f(s(
}
}
def check(id: String) = State[Cache, Option[User]]{
(c: Cache) => (c, c.get(id))
}
trait State[S, +A] {
}
trait State[S, +A] {
def run(initial: S): (S, A)
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State {
}
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
(_, _ )
}
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
(_, f(a))
}
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(_, f(a))
}
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(s, f(a))
}
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(s, f(a))
}
}
def flatMap[B](f: A => State[S,B]): State[S, B] =
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(s, f(a))
}
}
def flatMap[B](f: A => State[S,B]): State[S, B] =
f(a)
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(s, f(a))
}
}
def flatMap[B](f: A => State[S,B]): State[S, B] =
val (s, a) = run(s0)
f(a)
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(s, f(a))
}
}
def flatMap[B](f: A => State[S,B]): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
f(a)
}
}
}
trait State[S, +A] {
def run(initial: S): (S, A)
def map[B](f: A => B): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
(s, f(a))
}
}
def flatMap[B](f: A => State[S,B]): State[S, B] =
State { s0 =>
val (s, a) = run(s0)
f(a).run(s)
}
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ???
def retrieve(id: Long)(cache: Cache): (Cache, User) = ???
def findUser(id: Long)(cache: Cache): (Cache, User) = {
val (c, mu) = check(id)(cache)
mu match {
case Some(u) => (c, u)
case None => retrieve(id)(c)
}
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long)(cache: Cache): (Cache, Option[User]) = ???
def retrieve(id: Long)(cache: Cache): (Cache, User) = ???
def findUser(id: Long)(cache: Cache): (Cache, User) = {
val (c, mu) = check(id)(cache)
mu match {
case Some(u) => (c, u)
case None => retrieve(id)(c)
}
}
}
case class User(id: Long, fn: String, ln: String)
class Cache {}
def check(id: Long): State[Cache, Option[User]] = ???
def retrieve(id: Long): State[Cache, User] = ???
def findUser(id: Long): State[Cache, User] = {
for {
maybeUser <- check(id)
user <- maybeUser match {
case Some(u) => State { c => (c, u)}
case None => retrieve(id)
}
} yield (user)
}
Event Sourcing
Event Sourcing
driven by business
Bloggers Conf App
Bloggers Conf App
● Can create an account
Bloggers Conf App
● Can create an account
● List all bloggers already using the app
Bloggers Conf App
● Can create an account
● List all bloggers already using the app
● Mark/unmark other blogger as a friend
Bloggers Conf App
● Can create an account
● List all bloggers already using the app
● Mark/unmark other blogger as a friend
● Mark/unmark other blogger as an enemy
Bloggers Conf App
● Can create an account
● List all bloggers already using the app
● Mark/unmark other blogger as a friend
● Mark/unmark other blogger as an enemy
● Deactivate its account
Bloggers Conf App
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Bloggers Conf App
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
3 1
Bloggers Conf App
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
3 1
Enemies
id enemy_id
3 2
Bloggers Conf App
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
3 1
Enemies
id enemy_id
3 2
The Structure
Structure is not that
important
Structure is not that
important
Changes more often than behaviour
Start thinking about facts
occurring
Start thinking about facts
occurring
Derive structure from them
Blogger
Account
Created
(id=3)
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
Friends
id friend_id
Enemies
id enemy_id
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
Enemies
id enemy_id
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
3 1
Enemies
id enemy_id
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
3 1
Enemies
id enemy_id
3 2
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Befriended
Blogger
id=2
Unfriended
Blogger
id=2
Blogger
Account
Created
(id=3)
Befriended
Blogger
id=1
Made
Enemy of
Blogger
id=2
Event Sourcing
driven by business
Event Sourcing
The only model that does not lose data
“Enemy of my enemy is
my friend”
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
Friends
id friend_id
3 1
Enemies
id enemy_id
3 2
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
4 Tomasz Młynarski T
Friends
id friend_id
3 1
Enemies
id enemy_id
3 2
4 2
Bloggers
id first_name last_name active
1 Jan Kowalski T
2 Krystian Nowak T
3 Malgorzata Kucharska T
4 Tomasz Młynarski T
5 Monika Jagoda T
Friends
id friend_id
3 1
Enemies
id enemy_id
3 2
4 2
2 5
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
id = 3
id = 2
id = 1
id = 4
id = 5
id = 6
Benefits of Event Sourcing
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
● Built-in audit log
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
● Built-in audit log
● Enables temporal querying
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
● Built-in audit log
● Enables temporal querying
● Fits well with machine learning
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
● Built-in audit log
● Enables temporal querying
● Fits well with machine learning
● Preserves history - question not yet asked
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
● Built-in audit log
● Enables temporal querying
● Fits well with machine learning
● Preserves history - question not yet asked
● Writing regression tests is easy
Benefits of Event Sourcing
● Ability to go in time and figure out exactly what have
happened
● Scientific measurements over time, compare time
periods
● Built-in audit log
● Enables temporal querying
● Fits well with machine learning
● Preserves history - question not yet asked
● Writing regression tests is easy
● Polyglot data
Drawbacks of Event Sourcing
Drawbacks of Event Sourcing
● Historical record of your bad decisions
Drawbacks of Event Sourcing
● Historical record of your bad decisions
● Handling event duplicates
Drawbacks of Event Sourcing
● Historical record of your bad decisions
● Handling event duplicates
● Data eventually consistent
How to implement it?
Events vs Commands
Journal
Journal
Journal
val id = “”
val firstName: String = “”
val lastName: String = “”
val friends: List[String] =
List()
Journal
val id = “”
val firstName: String = “”
val lastName: String = “”
val friends: List[String] =
List()
Journal
val id = “”
val firstName: String = “”
val lastName: String = “”
val friends: List[String] =
List()
Journal
val id = “”
val firstName: String = “”
val lastName: String = “”
val friends: List[String] =
List()
Initialized(“1”, “Jan”, “Kowalski”
Journal
val id = “”
val firstName: String = “”
val lastName: String = “”
val friends: List[String] =
List()
Initialized(“1”, “Jan”, “Kowalski”
Journal
val id = “1”
val firstName: String =
“Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List()
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List()
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List()
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List()
Befriended(“10”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List()
Befriended(“10”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List(“10”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List(“10”, “31”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“31”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“31”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“31”)
validation
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“31”)
validation
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
validation
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
validation
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Befriended(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Befriended(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Befriended(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Befriended(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] = List
(“10”, “31”)
Befriend(“34”)
ACK
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List(“10”, “31”, “34”)
Befriend(“34”)
Journal
val id = “1”
val firstName: String = “Jan”
val lastName: String =
“Kowalski”
val friends: List[String] =
List(“10”, “31”, “34”)
Let’s see some code!
https://github.
com/rabbitonweb/es_cqrs_example
What we are missing?
What we are missing?
1. Read-model
What we are missing?
1. Read-model
2. Validation
And that’s all folks!
Paweł Szulc
Paweł Szulc
http://rabbitonweb.com
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
https://github.com/rabbitonweb/
Paweł Szulc
http://rabbitonweb.com
@rabbitonweb
https://github.com/rabbitonweb/
http://rabbitonweb.com/spark
Thank you!

More Related Content

What's hot

Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
Pawel Szulc
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
Christian Baranowski
 
ddd+scala
ddd+scaladdd+scala
ddd+scala
潤一 加藤
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
용 최
 
Groovy
GroovyGroovy
Groovy
Zen Urban
 
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
JaeYeoul Ahn
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
Bruno Scopelliti
 
Django101 geodjango
Django101 geodjangoDjango101 geodjango
Django101 geodjango
Calvin Cheng
 
RxSwift 시작하기
RxSwift 시작하기RxSwift 시작하기
RxSwift 시작하기
Suyeol Jeon
 
Poly-paradigm Java
Poly-paradigm JavaPoly-paradigm Java
Poly-paradigm Java
Pavel Tcholakov
 
Saving Gaia with GeoDjango
Saving Gaia with GeoDjangoSaving Gaia with GeoDjango
Saving Gaia with GeoDjango
Calvin Cheng
 
Groovy intro for OUDL
Groovy intro for OUDLGroovy intro for OUDL
Groovy intro for OUDL
J David Beutel
 
Grammarware Memes
Grammarware MemesGrammarware Memes
Grammarware Memes
Eelco Visser
 
Drools5 Community Training Module 3 Drools Expert DRL Syntax
Drools5 Community Training Module 3 Drools Expert DRL SyntaxDrools5 Community Training Module 3 Drools Expert DRL Syntax
Drools5 Community Training Module 3 Drools Expert DRL Syntax
Mauricio (Salaboy) Salatino
 
Groovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトークGroovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトーク
Tsuyoshi Yamamoto
 
JNI - Java & C in the same project
JNI - Java & C in the same projectJNI - Java & C in the same project
JNI - Java & C in the same project
Karol Wrótniak
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
intelliyole
 
はじめてのGroovy
はじめてのGroovyはじめてのGroovy
はじめてのGroovy
Tsuyoshi Yamamoto
 
Drools5 Community Training HandsOn 1 Drools DRL Syntax
Drools5 Community Training HandsOn 1 Drools DRL SyntaxDrools5 Community Training HandsOn 1 Drools DRL Syntax
Drools5 Community Training HandsOn 1 Drools DRL Syntax
Mauricio (Salaboy) Salatino
 

What's hot (20)

Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
ddd+scala
ddd+scaladdd+scala
ddd+scala
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
 
Groovy
GroovyGroovy
Groovy
 
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Django101 geodjango
Django101 geodjangoDjango101 geodjango
Django101 geodjango
 
RxSwift 시작하기
RxSwift 시작하기RxSwift 시작하기
RxSwift 시작하기
 
Poly-paradigm Java
Poly-paradigm JavaPoly-paradigm Java
Poly-paradigm Java
 
Saving Gaia with GeoDjango
Saving Gaia with GeoDjangoSaving Gaia with GeoDjango
Saving Gaia with GeoDjango
 
Groovy intro for OUDL
Groovy intro for OUDLGroovy intro for OUDL
Groovy intro for OUDL
 
Grammarware Memes
Grammarware MemesGrammarware Memes
Grammarware Memes
 
Drools5 Community Training Module 3 Drools Expert DRL Syntax
Drools5 Community Training Module 3 Drools Expert DRL SyntaxDrools5 Community Training Module 3 Drools Expert DRL Syntax
Drools5 Community Training Module 3 Drools Expert DRL Syntax
 
Groovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトークGroovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトーク
 
JNI - Java & C in the same project
JNI - Java & C in the same projectJNI - Java & C in the same project
JNI - Java & C in the same project
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
はじめてのGroovy
はじめてのGroovyはじめてのGroovy
はじめてのGroovy
 
Drools5 Community Training HandsOn 1 Drools DRL Syntax
Drools5 Community Training HandsOn 1 Drools DRL SyntaxDrools5 Community Training HandsOn 1 Drools DRL Syntax
Drools5 Community Training HandsOn 1 Drools DRL Syntax
 
Hw09 Hadoop + Clojure
Hw09   Hadoop + ClojureHw09   Hadoop + Clojure
Hw09 Hadoop + Clojure
 

Viewers also liked

Ficha de inscripción Danzas en el Hall
Ficha de inscripción Danzas en el HallFicha de inscripción Danzas en el Hall
Ficha de inscripción Danzas en el Hall
Pia D' Lucca
 
Tecnología Educativa IGY
Tecnología Educativa IGYTecnología Educativa IGY
Tecnología Educativa IGY
Yessi Pedroza Guzman
 
Circular 8
Circular 8Circular 8
Circular 8
JAVIER ORÁN
 
Venkatesh- planning CV
Venkatesh- planning CVVenkatesh- planning CV
Venkatesh- planning CVVenkatesh -
 
Polo tierra
Polo tierraPolo tierra
Polo tierra
karin gil
 
Business analytics and data mining
Business analytics and data miningBusiness analytics and data mining
Business analytics and data mining
Hoang Nguyen
 
Geminis
GeminisGeminis
GeminisGineNC
 
Sailesh CV-Planning Engineer
Sailesh CV-Planning EngineerSailesh CV-Planning Engineer
Sailesh CV-Planning Engineersailesh konduru
 
Quantum Computation and the Stabilizer Formalism for Error Correction
Quantum Computation and the Stabilizer Formalism for Error CorrectionQuantum Computation and the Stabilizer Formalism for Error Correction
Quantum Computation and the Stabilizer Formalism for Error CorrectionDaniel Bulhosa Solórzano
 

Viewers also liked (15)

Ficha de inscripción Danzas en el Hall
Ficha de inscripción Danzas en el HallFicha de inscripción Danzas en el Hall
Ficha de inscripción Danzas en el Hall
 
Salmos e hinos 012
Salmos e hinos 012Salmos e hinos 012
Salmos e hinos 012
 
Tecnología Educativa IGY
Tecnología Educativa IGYTecnología Educativa IGY
Tecnología Educativa IGY
 
Circular 8
Circular 8Circular 8
Circular 8
 
Tauro
Tauro Tauro
Tauro
 
Salmos e hinos 107
Salmos e hinos 107Salmos e hinos 107
Salmos e hinos 107
 
Research Lab Trainings
Research Lab TrainingsResearch Lab Trainings
Research Lab Trainings
 
DISTC Events Ref
DISTC Events RefDISTC Events Ref
DISTC Events Ref
 
Venkatesh- planning CV
Venkatesh- planning CVVenkatesh- planning CV
Venkatesh- planning CV
 
Blessed
BlessedBlessed
Blessed
 
Polo tierra
Polo tierraPolo tierra
Polo tierra
 
Business analytics and data mining
Business analytics and data miningBusiness analytics and data mining
Business analytics and data mining
 
Geminis
GeminisGeminis
Geminis
 
Sailesh CV-Planning Engineer
Sailesh CV-Planning EngineerSailesh CV-Planning Engineer
Sailesh CV-Planning Engineer
 
Quantum Computation and the Stabilizer Formalism for Error Correction
Quantum Computation and the Stabilizer Formalism for Error CorrectionQuantum Computation and the Stabilizer Formalism for Error Correction
Quantum Computation and the Stabilizer Formalism for Error Correction
 

Similar to Event Sourcing and Functional Programming

Introduction to Go
Introduction to GoIntroduction to Go
Introduction to Go
Jaehue Jang
 
3 things you must know to think reactive - Geecon Kraków 2015
3 things you must know to think reactive - Geecon Kraków 20153 things you must know to think reactive - Geecon Kraków 2015
3 things you must know to think reactive - Geecon Kraków 2015
Manuel Bernhardt
 
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Edureka!
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
Nelson Glauber Leal
 
Scala best practices
Scala best practicesScala best practices
Scala best practices
Alexander Zaidel
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
Istanbul Tech Talks
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
Fabernovel
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185
Mahmoud Samir Fayed
 
Java 5 New Feature
Java 5 New FeatureJava 5 New Feature
Java 5 New Feature
xcoda
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
scalaconfjp
 
Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout
source{d}
 
Introducing Command Line Applications with Ruby
Introducing Command Line Applications with RubyIntroducing Command Line Applications with Ruby
Introducing Command Line Applications with RubyNikhil Mungel
 
Python Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayPython Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard Way
Utkarsh Sengar
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05c
Kaz Yoshikawa
 
Message-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsMessage-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applications
Andrii Lashchenko
 
Minimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team ProductivityMinimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team Productivity
Derek Lee Boire
 
DevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreDevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a Datastore
Xavier Coulon
 

Similar to Event Sourcing and Functional Programming (20)

Introduction to Go
Introduction to GoIntroduction to Go
Introduction to Go
 
3 things you must know to think reactive - Geecon Kraków 2015
3 things you must know to think reactive - Geecon Kraków 20153 things you must know to think reactive - Geecon Kraków 2015
3 things you must know to think reactive - Geecon Kraków 2015
 
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
Scala best practices
Scala best practicesScala best practices
Scala best practices
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
Intro to Python
Intro to PythonIntro to Python
Intro to Python
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185
 
Java 5 New Feature
Java 5 New FeatureJava 5 New Feature
Java 5 New Feature
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
ProgrammingwithGOLang
ProgrammingwithGOLangProgrammingwithGOLang
ProgrammingwithGOLang
 
Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout
 
Django (Web Konferencia 2009)
Django (Web Konferencia 2009)Django (Web Konferencia 2009)
Django (Web Konferencia 2009)
 
Introducing Command Line Applications with Ruby
Introducing Command Line Applications with RubyIntroducing Command Line Applications with Ruby
Introducing Command Line Applications with Ruby
 
Python Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayPython Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard Way
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05c
 
Message-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsMessage-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applications
 
Minimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team ProductivityMinimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team Productivity
 
DevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreDevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a Datastore
 

More from GlobalLogic Ukraine

GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Ukraine
 
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic Ukraine
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxШтучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptx
GlobalLogic Ukraine
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxЗадачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptx
GlobalLogic Ukraine
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxЩо треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Ukraine
 
JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"
GlobalLogic Ukraine
 
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic Ukraine
 
Страх і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationСтрах і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic Education
GlobalLogic Ukraine
 
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic Ukraine
 
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic Ukraine
 
“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Ukraine
 
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic Ukraine
 
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
GlobalLogic Ukraine
 
GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Ukraine
 
C++ Webinar "Why Should You Learn C++ in 2021-22?"
C++ Webinar "Why Should You Learn C++ in 2021-22?"C++ Webinar "Why Should You Learn C++ in 2021-22?"
C++ Webinar "Why Should You Learn C++ in 2021-22?"
GlobalLogic Ukraine
 
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Ukraine
 

More from GlobalLogic Ukraine (20)

GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
 
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
 
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxШтучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptx
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxЗадачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptx
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxЩо треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
 
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
 
JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"
 
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
 
Страх і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationСтрах і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic Education
 
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
 
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
 
“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?
 
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
 
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
 
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
 
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
 
GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"
 
C++ Webinar "Why Should You Learn C++ in 2021-22?"
C++ Webinar "Why Should You Learn C++ in 2021-22?"C++ Webinar "Why Should You Learn C++ in 2021-22?"
C++ Webinar "Why Should You Learn C++ in 2021-22?"
 
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
 

Recently uploaded

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
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
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
kalichargn70th171
 
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
 
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
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
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
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
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
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
pavan998932
 
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
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 

Recently uploaded (20)

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
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
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
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
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 

Event Sourcing and Functional Programming

  • 1. Functional Programming & Event Sourcing A pair made in heaven twitter: @rabbitonweb, email: paul.szulc@gmail.com
  • 3. ● no assignment statements
  • 4. ● no assignment statements ● no variables
  • 5. ● no assignment statements ● no variables ● once given a value, never change
  • 6. ● no assignment statements ● no variables ● once given a value, never change ● no side-effects at all
  • 7. ● no assignment statements ● no variables ● once given a value, never change ● no side-effects at all
  • 8. “The functional programmer sounds rather like a mediæval monk,
  • 9. “The functional programmer sounds rather like a mediæval monk, denying himself the pleasures of life
  • 10. “The functional programmer sounds rather like a mediæval monk, denying himself the pleasures of life in the hope that it will make him virtuous.”
  • 12. case class User(id: Long, fn: String, ln: String)
  • 13. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? }
  • 14. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? }
  • 15. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? } class UserFinder(cache: Cache, repo: UserRepo) { }
  • 16. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? } class UserFinder(cache: Cache, repo: UserRepo) { def findUser(id: Long): User = { } }
  • 17. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? } class UserFinder(cache: Cache, repo: UserRepo) { def findUser(id: Long): User = { val maybeUser: Option[User] = cache.check(id) } }
  • 18. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? } class UserFinder(cache: Cache, repo: UserRepo) { def findUser(id: Long): User = { val maybeUser: Option[User] = cache.check(id) if (maybeUser.isDefined) { maybeUser.get } } }
  • 19. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? } class UserFinder(cache: Cache, repo: UserRepo) { def findUser(id: Long): User = { val maybeUser: Option[User] = cache.check(id) if (maybeUser.isDefined) { maybeUser.get } else { val user: User = repo.retrieve(id) cache.insert(user.id, user) } } }
  • 20. No concept of ‘time’
  • 24. input f(input): output output g(input): output
  • 25. input f(input): output output g(input): output output
  • 26. input f(input): output output g(input): output output
  • 27. h = g o f input f(input): output output g(input): output output
  • 29. h = g o f input f(input): output output g(input): output output
  • 30. /** * This function returns a reversed list * @param list A list to be reversed * @return A reversed list */ public List<T> reverse(List<t> list) { ??? }
  • 31.
  • 32. /** * This function returns a reversed list * @param list A list to be reversed * @return A reversed list */ public List<T> reverse(List<t> list) { ??? }
  • 33. /** * This function returns a reversed list * @param list A list to be reversed public List<T> reverse(List<t> list) { ??? }
  • 34. /** * This function returns a reversed list public List<T> reverse(List<t> list) { ??? }
  • 37. public List<T> reverse(List<t> list) { return list.sort(); }
  • 43. def smdfknmsdfp(a: Int): Int = a = a + 10 = 10
  • 44. “Why Functional Programming Matters” J. Hughes http://comjnl.oxfordjournals.org/content/32/2/98. full.pdf
  • 45. “Why Functional Programming Matters” J. Hughes, Nov. 1988 http://comjnl.oxfordjournals.org/content/32/2/98. full.pdf
  • 46. Soft introduction “Why Functional Programming Matters” J. Hughes, Nov. 1988 http://comjnl.oxfordjournals.org/content/32/2/98. full.pdf
  • 47. “Program Design by Calculation” J.N. Oliveira http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
  • 48. “Program Design by Calculation” J.N. Oliveira, Draft http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
  • 49. Patterns in FP World “Program Design by Calculation” J.N. Oliveira, Draft http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
  • 50. Patterns in FP World Math Matters “Program Design by Calculation” J.N. Oliveira, Draft http://www4.di.uminho.pt/~jno/ps/pdbc_part.pdf
  • 51. “A lengthy approach to Haskell fundamentals” http://www.davesquared.net/2012/05/lengthy- approach-to-haskell.html
  • 54.
  • 55.
  • 56.
  • 57. How to do something useful?
  • 58. How to do something useful?
  • 59. case class User(id: Long, fn: String, ln: String) class Cache { def check(id: Long): Option[User] = ??? } case class UserRepo(cache: Cache) { def retrieve(id: Long): User = ??? } class UserFinder(cache: Cache, repo: UserRepo) { def findUser(id: Long): User = { val maybeUser: Option[User] = cache.check(id) if (maybeUser.isDefined) { maybeUser.get } else { val user: User = repo.retrieve(id) cache.insert(user.id, user) } } }
  • 60. case class User(id: Long, fn: String, ln: String)
  • 61. case class User(id: Long, fn: String, ln: String) class Cache {}
  • 62. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ...
  • 63. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ... def retrieve(id: Long)(cache: Cache): (Cache, User) = ...
  • 64. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ... def retrieve(id: Long)(cache: Cache): (Cache, User) = ... def findUser(id: Long)(cache: Cache): (Cache, User) = { } }
  • 65. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ... def retrieve(id: Long)(cache: Cache): (Cache, User) = ... def findUser(id: Long)(cache: Cache): (Cache, User) = { val (c, mu) = check(id)(cache) } }
  • 66. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ... def retrieve(id: Long)(cache: Cache): (Cache, User) = ... def findUser(id: Long)(cache: Cache): (Cache, User) = { val (c, mu) = check(id)(cache) mu match { case Some(u) => (c, u) } } }
  • 67. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ... def retrieve(id: Long)(cache: Cache): (Cache, User) = ... def findUser(id: Long)(cache: Cache): (Cache, User) = { val (c, mu) = check(id)(cache) mu match { case Some(u) => (c, u) case None => retrieve(id)(c) } } }
  • 68. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ... def retrieve(id: Long)(cache: Cache): (Cache, User) = ... def findUser(id: Long)(cache: Cache): (Cache, User) = { val (c, mu) = check(id)(cache) mu match { case Some(u) => (c, u) case None => retrieve(id)(c) } } }
  • 69. S => (S, A)
  • 71. State[S, A] S => (S, A) .run(S)
  • 72. State[S, A] S => (S, A) .map(A => B): State[S, B]
  • 73. State[S, A] S => (S, A) .flatMap(A => State[S, B]): State[S,B]
  • 74. object State { def apply[S, A] (f: S => (S,A)): State[S, A] = }
  • 75. object State { def apply[S, A] (f: S => (S,A)): State[S, A] = new State[S, A] { def run(s: S) = f(s) } }
  • 76. object State { def apply[S, A] (f: S => (S,A)): State[S, A] = new State[S, A] { def run(s: S) = f(s) } } def check(id: String) =
  • 77. object State { def apply[S, A] (f: S => (S,A)): State[S, A] = new State[S, A] { def run(s: S) = f(s) } } def check(id: String) = (c: Cache) => (c, c.get(id))
  • 78. object State { def apply[S, A] (f: S => (S,A)): State[S, A] = new State[S, A] { def run(s: S) = f(s) } } def check(id: String) = State[Cache, Option[User]].apply { (c: Cache) => (c, c.get(id)) }
  • 79. object State { def apply[S, A] (f: S => (S,A)): State[S, A] = new State[S, A] { def run(s: S) = f(s( } } def check(id: String) = State[Cache, Option[User]]{ (c: Cache) => (c, c.get(id)) }
  • 81. trait State[S, +A] { def run(initial: S): (S, A) }
  • 82. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = } }
  • 83. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { } } }
  • 84. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => (_, _ ) } } }
  • 85. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => (_, f(a)) } } }
  • 86. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (_, f(a)) } } }
  • 87. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (s, f(a)) } } }
  • 88. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (s, f(a)) } } def flatMap[B](f: A => State[S,B]): State[S, B] = } }
  • 89. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (s, f(a)) } } def flatMap[B](f: A => State[S,B]): State[S, B] = f(a) } }
  • 90. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (s, f(a)) } } def flatMap[B](f: A => State[S,B]): State[S, B] = val (s, a) = run(s0) f(a) } }
  • 91. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (s, f(a)) } } def flatMap[B](f: A => State[S,B]): State[S, B] = State { s0 => val (s, a) = run(s0) f(a) } } }
  • 92. trait State[S, +A] { def run(initial: S): (S, A) def map[B](f: A => B): State[S, B] = State { s0 => val (s, a) = run(s0) (s, f(a)) } } def flatMap[B](f: A => State[S,B]): State[S, B] = State { s0 => val (s, a) = run(s0) f(a).run(s) } } }
  • 93. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ??? def retrieve(id: Long)(cache: Cache): (Cache, User) = ??? def findUser(id: Long)(cache: Cache): (Cache, User) = { val (c, mu) = check(id)(cache) mu match { case Some(u) => (c, u) case None => retrieve(id)(c) } } }
  • 94. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long)(cache: Cache): (Cache, Option[User]) = ??? def retrieve(id: Long)(cache: Cache): (Cache, User) = ??? def findUser(id: Long)(cache: Cache): (Cache, User) = { val (c, mu) = check(id)(cache) mu match { case Some(u) => (c, u) case None => retrieve(id)(c) } } }
  • 95. case class User(id: Long, fn: String, ln: String) class Cache {} def check(id: Long): State[Cache, Option[User]] = ??? def retrieve(id: Long): State[Cache, User] = ??? def findUser(id: Long): State[Cache, User] = { for { maybeUser <- check(id) user <- maybeUser match { case Some(u) => State { c => (c, u)} case None => retrieve(id) } } yield (user) }
  • 99. Bloggers Conf App ● Can create an account
  • 100. Bloggers Conf App ● Can create an account ● List all bloggers already using the app
  • 101. Bloggers Conf App ● Can create an account ● List all bloggers already using the app ● Mark/unmark other blogger as a friend
  • 102. Bloggers Conf App ● Can create an account ● List all bloggers already using the app ● Mark/unmark other blogger as a friend ● Mark/unmark other blogger as an enemy
  • 103. Bloggers Conf App ● Can create an account ● List all bloggers already using the app ● Mark/unmark other blogger as a friend ● Mark/unmark other blogger as an enemy ● Deactivate its account
  • 104. Bloggers Conf App Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T
  • 105. Bloggers Conf App Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id 3 1
  • 106. Bloggers Conf App Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id 3 1 Enemies id enemy_id 3 2
  • 107. Bloggers Conf App Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id 3 1 Enemies id enemy_id 3 2 The Structure
  • 108. Structure is not that important
  • 109. Structure is not that important Changes more often than behaviour
  • 110. Start thinking about facts occurring
  • 111. Start thinking about facts occurring Derive structure from them
  • 115. Blogger Account Created (id=3) Befriended Blogger id=1 Made Enemy of Blogger id=2 Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T Friends id friend_id Enemies id enemy_id
  • 116. Blogger Account Created (id=3) Befriended Blogger id=1 Made Enemy of Blogger id=2 Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id Enemies id enemy_id
  • 117. Blogger Account Created (id=3) Befriended Blogger id=1 Made Enemy of Blogger id=2 Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id 3 1 Enemies id enemy_id
  • 118. Blogger Account Created (id=3) Befriended Blogger id=1 Made Enemy of Blogger id=2 Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id 3 1 Enemies id enemy_id 3 2
  • 122. Event Sourcing The only model that does not lose data
  • 123. “Enemy of my enemy is my friend”
  • 124. Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T Friends id friend_id 3 1 Enemies id enemy_id 3 2
  • 125. Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T 4 Tomasz Młynarski T Friends id friend_id 3 1 Enemies id enemy_id 3 2 4 2
  • 126. Bloggers id first_name last_name active 1 Jan Kowalski T 2 Krystian Nowak T 3 Malgorzata Kucharska T 4 Tomasz Młynarski T 5 Monika Jagoda T Friends id friend_id 3 1 Enemies id enemy_id 3 2 4 2 2 5
  • 127. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 128. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 129. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 130. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 131. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 132. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 133. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 134. id = 3 id = 2 id = 1 id = 4 id = 5 id = 6
  • 135. Benefits of Event Sourcing
  • 136. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened
  • 137. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods
  • 138. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods ● Built-in audit log
  • 139. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods ● Built-in audit log ● Enables temporal querying
  • 140. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods ● Built-in audit log ● Enables temporal querying ● Fits well with machine learning
  • 141. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods ● Built-in audit log ● Enables temporal querying ● Fits well with machine learning ● Preserves history - question not yet asked
  • 142. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods ● Built-in audit log ● Enables temporal querying ● Fits well with machine learning ● Preserves history - question not yet asked ● Writing regression tests is easy
  • 143. Benefits of Event Sourcing ● Ability to go in time and figure out exactly what have happened ● Scientific measurements over time, compare time periods ● Built-in audit log ● Enables temporal querying ● Fits well with machine learning ● Preserves history - question not yet asked ● Writing regression tests is easy ● Polyglot data
  • 144. Drawbacks of Event Sourcing
  • 145. Drawbacks of Event Sourcing ● Historical record of your bad decisions
  • 146. Drawbacks of Event Sourcing ● Historical record of your bad decisions ● Handling event duplicates
  • 147. Drawbacks of Event Sourcing ● Historical record of your bad decisions ● Handling event duplicates ● Data eventually consistent
  • 152. Journal val id = “” val firstName: String = “” val lastName: String = “” val friends: List[String] = List()
  • 153. Journal val id = “” val firstName: String = “” val lastName: String = “” val friends: List[String] = List()
  • 154. Journal val id = “” val firstName: String = “” val lastName: String = “” val friends: List[String] = List()
  • 155. Journal val id = “” val firstName: String = “” val lastName: String = “” val friends: List[String] = List() Initialized(“1”, “Jan”, “Kowalski”
  • 156. Journal val id = “” val firstName: String = “” val lastName: String = “” val friends: List[String] = List() Initialized(“1”, “Jan”, “Kowalski”
  • 157. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List()
  • 158. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List()
  • 159. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List()
  • 160. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List() Befriended(“10”)
  • 161. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List() Befriended(“10”)
  • 162. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List(“10”)
  • 163. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”)
  • 164. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”)
  • 165. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”)
  • 166. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List(“10”, “31”)
  • 167. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”)
  • 168. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“31”)
  • 169. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“31”)
  • 170. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“31”) validation
  • 171. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“31”) validation
  • 172. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”)
  • 173. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”)
  • 174. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”)
  • 175. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) validation
  • 176. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) validation
  • 177. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) Befriended(“34”)
  • 178. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) Befriended(“34”)
  • 179. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) Befriended(“34”)
  • 180. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) Befriended(“34”)
  • 181. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”)
  • 182. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List (“10”, “31”) Befriend(“34”) ACK
  • 183. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List(“10”, “31”, “34”) Befriend(“34”)
  • 184. Journal val id = “1” val firstName: String = “Jan” val lastName: String = “Kowalski” val friends: List[String] = List(“10”, “31”, “34”)
  • 185. Let’s see some code! https://github. com/rabbitonweb/es_cqrs_example
  • 186. What we are missing?
  • 187. What we are missing? 1. Read-model
  • 188. What we are missing? 1. Read-model 2. Validation
  • 189. And that’s all folks!