SlideShare ist ein Scribd-Unternehmen logo
1 von 194
Downloaden Sie, um offline zu lesen
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!

Weitere ähnliche Inhalte

Was ist angesagt?

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
 

Was ist angesagt? (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
 

Andere mochten auch

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
 

Andere mochten auch (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...
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Mehr von 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
 

Mehr von 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
 

Kürzlich hochgeladen

Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesKrzysztofKkol1
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profileakrivarotava
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...Akihiro Suda
 
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
 
Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Anthony Dahanne
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
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
 
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
 

Kürzlich hochgeladen (20)

Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profile
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
 
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...
 
Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
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
 
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
 

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!