SlideShare a Scribd company logo
1 of 194
Download to read offline
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/
Thank you!

More Related Content

What's hot

Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In JavaAndrei Solntsev
 
Programming Under Linux In Python
Programming Under Linux In PythonProgramming Under Linux In Python
Programming Under Linux In PythonMarwan Osman
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance PythonIan Ozsvald
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftGiordano Scalzo
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorFedor Lavrentyev
 
Android & Kotlin - The code awakens #03
Android & Kotlin - The code awakens #03Android & Kotlin - The code awakens #03
Android & Kotlin - The code awakens #03Omar Miatello
 
Learn python in 20 minutes
Learn python in 20 minutesLearn python in 20 minutes
Learn python in 20 minutesSidharth Nadhan
 
Android & Kotlin - The code awakens #02
Android & Kotlin - The code awakens #02Android & Kotlin - The code awakens #02
Android & Kotlin - The code awakens #02Omar Miatello
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101Ankur Gupta
 
Introduction to advanced python
Introduction to advanced pythonIntroduction to advanced python
Introduction to advanced pythonCharles-Axel Dein
 
Python and sysadmin I
Python and sysadmin IPython and sysadmin I
Python and sysadmin IGuixing Bai
 
Python Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutPython Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutAudrey Roy
 
Python for Linux System Administration
Python for Linux System AdministrationPython for Linux System Administration
Python for Linux System Administrationvceder
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimizationg3_nittala
 
Kotlin - lo Swift di Android
Kotlin - lo Swift di AndroidKotlin - lo Swift di Android
Kotlin - lo Swift di AndroidOmar Miatello
 
Introduction to python
Introduction to pythonIntroduction to python
Introduction to pythonAhmed Salama
 
Matlab and Python: Basic Operations
Matlab and Python: Basic OperationsMatlab and Python: Basic Operations
Matlab and Python: Basic OperationsWai Nwe Tun
 

What's hot (20)

Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Don't do this
Don't do thisDon't do this
Don't do this
 
Programming Under Linux In Python
Programming Under Linux In PythonProgramming Under Linux In Python
Programming Under Linux In Python
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance Python
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in Swift
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
 
Android & Kotlin - The code awakens #03
Android & Kotlin - The code awakens #03Android & Kotlin - The code awakens #03
Android & Kotlin - The code awakens #03
 
Learn python in 20 minutes
Learn python in 20 minutesLearn python in 20 minutes
Learn python in 20 minutes
 
Android & Kotlin - The code awakens #02
Android & Kotlin - The code awakens #02Android & Kotlin - The code awakens #02
Android & Kotlin - The code awakens #02
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101
 
Introduction to advanced python
Introduction to advanced pythonIntroduction to advanced python
Introduction to advanced python
 
Python and sysadmin I
Python and sysadmin IPython and sysadmin I
Python and sysadmin I
 
Python Tricks That You Can't Live Without
Python Tricks That You Can't Live WithoutPython Tricks That You Can't Live Without
Python Tricks That You Can't Live Without
 
Python for Linux System Administration
Python for Linux System AdministrationPython for Linux System Administration
Python for Linux System Administration
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimization
 
Google guava
Google guavaGoogle guava
Google guava
 
Python Tutorial
Python TutorialPython Tutorial
Python Tutorial
 
Kotlin - lo Swift di Android
Kotlin - lo Swift di AndroidKotlin - lo Swift di Android
Kotlin - lo Swift di Android
 
Introduction to python
Introduction to pythonIntroduction to python
Introduction to python
 
Matlab and Python: Basic Operations
Matlab and Python: Basic OperationsMatlab and Python: Basic Operations
Matlab and Python: Basic Operations
 

Viewers also liked

Apache spark when things go wrong
Apache spark   when things go wrongApache spark   when things go wrong
Apache spark when things go wrongPawel Szulc
 
The cats toolbox a quick tour of some basic typeclasses
The cats toolbox  a quick tour of some basic typeclassesThe cats toolbox  a quick tour of some basic typeclasses
The cats toolbox a quick tour of some basic typeclassesPawel Szulc
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 minPawel Szulc
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classesPawel Szulc
 
Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)Chris Richardson
 
Writing your own RDD for fun and profit
Writing your own RDD for fun and profitWriting your own RDD for fun and profit
Writing your own RDD for fun and profitPawel Szulc
 
Functional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modelingFunctional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modelingDebasish Ghosh
 
Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain EventsSteven Smith
 
“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”Pawel Szulc
 
Apache spark workshop
Apache spark workshopApache spark workshop
Apache spark workshopPawel Szulc
 
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...Chris Richardson
 
Going bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data typesGoing bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data typesPawel Szulc
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs FreePawel Szulc
 
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Chris Richardson
 
From C to Q one event at a time: Event Sourcing illustrated
From C to Q one event at a time: Event Sourcing illustratedFrom C to Q one event at a time: Event Sourcing illustrated
From C to Q one event at a time: Event Sourcing illustratedLorenzo Nicora
 
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...Chris Richardson
 

Viewers also liked (19)

Apache spark when things go wrong
Apache spark   when things go wrongApache spark   when things go wrong
Apache spark when things go wrong
 
How do event loops work in Python?
How do event loops work in Python?How do event loops work in Python?
How do event loops work in Python?
 
The cats toolbox a quick tour of some basic typeclasses
The cats toolbox  a quick tour of some basic typeclassesThe cats toolbox  a quick tour of some basic typeclasses
The cats toolbox a quick tour of some basic typeclasses
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
 
Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)
 
Writing your own RDD for fun and profit
Writing your own RDD for fun and profitWriting your own RDD for fun and profit
Writing your own RDD for fun and profit
 
Functional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modelingFunctional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modeling
 
Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain Events
 
“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”“Going bananas with recursion schemes for fixed point data types”
“Going bananas with recursion schemes for fixed point data types”
 
Apache spark workshop
Apache spark workshopApache spark workshop
Apache spark workshop
 
Domain Event - The Hidden Gem of DDD
Domain Event - The Hidden Gem of DDDDomain Event - The Hidden Gem of DDD
Domain Event - The Hidden Gem of DDD
 
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
 
Going bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data typesGoing bananas with recursion schemes for fixed point data types
Going bananas with recursion schemes for fixed point data types
 
Make your programs Free
Make your programs FreeMake your programs Free
Make your programs Free
 
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
 
From C to Q one event at a time: Event Sourcing illustrated
From C to Q one event at a time: Event Sourcing illustratedFrom C to Q one event at a time: Event Sourcing illustrated
From C to Q one event at a time: Event Sourcing illustrated
 
Event-sourced architectures with Akka
Event-sourced architectures with AkkaEvent-sourced architectures with Akka
Event-sourced architectures with Akka
 
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
 

Similar to Functional Programming & Event Sourcing - a pair made in heaven

Introduction to Go
Introduction to GoIntroduction to Go
Introduction to GoJaehue Jang
 
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티JaeYeoul Ahn
 
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 2015Manuel 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 LibraryNelson Glauber Leal
 
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 ProgrammingIstanbul 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 185Mahmoud Samir Fayed
 
Java 5 New Feature
Java 5 New FeatureJava 5 New Feature
Java 5 New Featurexcoda
 
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 WayUtkarsh Sengar
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05cKaz 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 applicationsAndrii 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 ProductivityDerek Lee Boire
 

Similar to Functional Programming & Event Sourcing - a pair made in heaven (20)

Introduction to Go
Introduction to GoIntroduction to Go
Introduction to Go
 
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
Go 프로그래밍 소개 - 장재휴, DomainDriven커뮤니티
 
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
 

More from Pawel Szulc

Getting acquainted with Lens
Getting acquainted with LensGetting acquainted with Lens
Getting acquainted with LensPawel Szulc
 
Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Pawel Szulc
 
Painless Haskell
Painless HaskellPainless Haskell
Painless HaskellPawel Szulc
 
Trip with monads
Trip with monadsTrip with monads
Trip with monadsPawel Szulc
 
Trip with monads
Trip with monadsTrip with monads
Trip with monadsPawel Szulc
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineersPawel Szulc
 
RChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiRChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiPawel Szulc
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineersPawel Szulc
 
Understanding distributed calculi in Haskell
Understanding distributed calculi in HaskellUnderstanding distributed calculi in Haskell
Understanding distributed calculi in HaskellPawel Szulc
 
Software engineering the genesis
Software engineering  the genesisSoftware engineering  the genesis
Software engineering the genesisPawel Szulc
 
Category theory is general abolute nonsens
Category theory is general abolute nonsensCategory theory is general abolute nonsens
Category theory is general abolute nonsensPawel Szulc
 
Know your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmKnow your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmPawel Szulc
 
Apache Spark 101 [in 50 min]
Apache Spark 101 [in 50 min]Apache Spark 101 [in 50 min]
Apache Spark 101 [in 50 min]Pawel Szulc
 
Javascript development done right
Javascript development done rightJavascript development done right
Javascript development done rightPawel Szulc
 
Architektura to nie bzdura
Architektura to nie bzduraArchitektura to nie bzdura
Architektura to nie bzduraPawel Szulc
 
Testing and Testable Code
Testing and Testable CodeTesting and Testable Code
Testing and Testable CodePawel Szulc
 

More from Pawel Szulc (17)

Getting acquainted with Lens
Getting acquainted with LensGetting acquainted with Lens
Getting acquainted with Lens
 
Impossibility
ImpossibilityImpossibility
Impossibility
 
Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)Maintainable Software Architecture in Haskell (with Polysemy)
Maintainable Software Architecture in Haskell (with Polysemy)
 
Painless Haskell
Painless HaskellPainless Haskell
Painless Haskell
 
Trip with monads
Trip with monadsTrip with monads
Trip with monads
 
Trip with monads
Trip with monadsTrip with monads
Trip with monads
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineers
 
RChain - Understanding Distributed Calculi
RChain - Understanding Distributed CalculiRChain - Understanding Distributed Calculi
RChain - Understanding Distributed Calculi
 
Illogical engineers
Illogical engineersIllogical engineers
Illogical engineers
 
Understanding distributed calculi in Haskell
Understanding distributed calculi in HaskellUnderstanding distributed calculi in Haskell
Understanding distributed calculi in Haskell
 
Software engineering the genesis
Software engineering  the genesisSoftware engineering  the genesis
Software engineering the genesis
 
Category theory is general abolute nonsens
Category theory is general abolute nonsensCategory theory is general abolute nonsens
Category theory is general abolute nonsens
 
Know your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmKnow your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvm
 
Apache Spark 101 [in 50 min]
Apache Spark 101 [in 50 min]Apache Spark 101 [in 50 min]
Apache Spark 101 [in 50 min]
 
Javascript development done right
Javascript development done rightJavascript development done right
Javascript development done right
 
Architektura to nie bzdura
Architektura to nie bzduraArchitektura to nie bzdura
Architektura to nie bzdura
 
Testing and Testable Code
Testing and Testable CodeTesting and Testable Code
Testing and Testable Code
 

Recently uploaded

办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 

Recently uploaded (20)

办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 

Functional Programming & Event Sourcing - a pair made in heaven

  • 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!