As time goes by…
Episode 2: technical challenges of bi-temporal Event Sourcing
@tpierrain
t
If you want
to win…
Tweet like hell on…
#newCrafts
REQUIREMENTS
—
REQUIREMENTS
—
Understand their former decisions
REQUIREMENTS
—
Understand their former decisions

Fix their perception of the world
retroactively
REQUIREMENTS
—
Understand their former decisions

Fix their perception of the world
retroactively

(Re)produce reports in and from the past
REQUIREMENTS
—
Understand their former decisions

Fix their perception of the world
retroactively

(Re)produce reports in and from the past 

Forecast ”events” in the future

REQUIREMENTS
—
Understand their former decisions

Fix their perception of the world
retroactively

(Re)produce reports in and from the past 

Forecast ”events” in the future

Strong audit trail
They needed a time machine
Event Sourcing baby!
Event Sourcing 101
Remember your banking account?
Event Sourcing
Event Sourcing
Final state of the world
All changes since 

the beginning
All changes since the beginning
=
A list of events
Event [ɪˈvent]

Describes a fact, something that have happened.
Usually expressed in a past-tense form.

(e.g.: TalkStarted)
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Properties / Members
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Evolution functions
Change state
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Constructor
Change state
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Decision functions
Don’t change state
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Decision functions
Don’t change state
Event-Sourced business objects
Event-Sourced business objects
public class Fund : EventSourcedAggregate
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Fund(IEnumerable<Event> events)
{
foreach(var evt in events)
{
Apply(evt);
}
}
private Apply(FundRenamed event)
{
this.Name = event.FundNewName;
}
public IEnumerable<Event> Rename(string newName)
{
!// business logic and invariants checks HERE
!// Raise event(s)
return new[] { new FundRenamed(this.Id, newName) };
}
}
Decision functions
Don’t change state
Evolution functions
Change state
Projection [prəˈjekSHən]

Deriving a current state from a stream of events
Fund myFund = fundRepository.GetById(fundId, projectedAt);
Event-Sourcing in motion
Guid
timestamp
Fund myFund = fundRepository.GetById(fundId, projectedAt);
Now
b7f3ddfb-2cb5….
Event-Sourcing in motion
t
Fund
id:
Name:
Creation date:
Management Company:
Shares:
Event-Sourcing in motion
t
FundCreated

“super yield ”
Jan 1st

2016
Fund
id: b7f3ddfb -2cb5….
Name: super yield
Creation date: Jan 1st
2016
Management Company:
Shares:
Event-Sourcing in motion
t
Jan 1st

2016
ManagementCompanyAssigned

“BNP”
Jan 30th

2016
Fund
id: b7f3ddfb -2cb5….
Name: super yield
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Event-Sourcing in motion
t
Jan 1st

2016
Jan 30th

2016
FundRenamed

“Yield 2k22”
Apr 1st

2016
Fund
id: b7f3ddfb -2cb5….
Name: Yield 2k22
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Event-Sourcing in motion
t
Jan 1st

2016
Jan 30th

2016
Apr 1st

2016
ShareAdded

“Part D”
Jun 2nd

2016
Fund
id: b7f3ddfb -2cb5….
Name: Yield 2k22
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Part D
Event-Sourcing in motion
Fund
id: b7f3ddfb -2cb5….
Name: Yield 2k22
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Part D
End of
Stream
>> <<t
Jan 1st

2016
Jan 30th

2016
Apr 1st

2016
Jun 2nd

2016
Event-Sourcing in motion
Projected at now
Ready to work
Fund
id: b7f3ddfb -2cb5….
Name: Yield 2k22
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Part D
The beauty of it
Pick the projection date you want ;-)
Project same Fund at Apr 1st 2016
(same stream of events)
Event-Sourcing in motion
t
Fund
id:
Name:
Creation date:
Management Company:
Shares:
Event-Sourcing in motion
t
FundCreated

“super yield ”
Jan 1st

2016
Fund
id: b7f3ddfb -2cb5….
Name: super yield
Creation date: Jan 1st
2016
Management Company:
Shares:
Event-Sourcing in motion
t
Jan 1st

2016
ManagementCompanyAssigned

“BNP”
Jan 30th

2016
Fund
id: b7f3ddfb -2cb5….
Name: super yield
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Event-Sourcing in motion
t
Jan 1st

2016
Jan 30th

2016
FundRenamed

“Yield 2k22”
Apr 1st

2016
Fund
id: b7f3ddfb -2cb5….
Name: Yield 2k22
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
Event-Sourcing in motion
t
Jan 1st

2016
Jan 30th

2016
Apr 1st

2016
Fund
id: b7f3ddfb -2cb5….
Name: Yield 2k22
Creation date: Jan 1st
2016
Management Company:
BNP
Shares:
We’re
done here
;-)
>> <<
Event-Sourcing in motion
Command [kəˈmɑːnd]

Triggers an action. Modify the state of the system
e.g.: RenameFund
Commands are used to take decisions and to raise events.
Commands are used to take decisions and to raise events.
Command
(RenameFund)
Aggregate
(Fund X)
Commands are used to take decisions and to raise events.
Command
(RenameFund)
Events
(FundRenamed)
Events are used to restore/change the state of our aggregates.
Aggregate
(Fund X)
so far so good?
😉
Specificities
of bi-temporal
event sourcing
& Challenges
Challenge #1
How to change what can’t be changed?

Challenge #1
- Events are immutable (facts)
- We save them in append-only streams (Event Store)
t
Q: How to retroactively change former mistaken events?

Q: How to insert forgotten events in the past (in the middle of
a stream)?
we don’t change events
we just add
more events
we don’t change events
we just add
more events
“One more thing…”
“One more thing…
All our events have…”
createdAt 


validFrom !-> when it applies
2 timestamps
createdAt 


validFrom !-> when it applies
2 timestamps
( bi-temporal)
Types of events
validFrom
createdAt
Classic event
Types of events
validFrom
createdAt
Classic event
validFrom createdAt
Retroactive event
Thus we can hide former events
Thus we can hide former events
t
Feb 1st

2016
Feb 3rd

2016
Feb 5th

2016
“new naaame”
“initial name”
Thus we can hide former events
t
Feb 1st

2016
Feb 3rd

2016
Feb 5th

2016
“new naaame”
“initial name”
“fixed name ;-)”
Thus we can hide former events
t
Feb 1st

2016
Feb 3rd

2016
Feb 5th

2016
“new naaame”
“initial name”
“fixed name ;-)”
Challenge #2
Forecasting “facts”?!?
Challenge #2
- Event Store stores “Events” ;-)
- Events are things that have already happened (facts)
t
Q: How to store things that have to happen in an Event Store?
Let’s store ”a Command (X) has just been Scheduled” events
validFromcreatedAt
“Command Scheduled” event“Command Scheduled” event
RenameFund
(Cmd)
validFromcreatedAt
CommandScheduled<RenameFund> event
RenameFund
(Cmd)
3 Types of events
3 Types of events
validFrom
createdAt
Classic event
3 Types of events
validFrom
createdAt
Classic event
validFrom createdAt
Retroactive event
3 Types of events
validFrom
createdAt
Classic event
validFrom createdAt
Retroactive event
validFromcreatedAt
“Command Scheduled” event
C
Our model
Challenge #3
How to project unsorted streams of
events?
Challenge #3
- With retroactive events, we have unsorted streams of events
- Some events may hide others
- Past may change at any time. Future too
t
Q: How to implement projections in such environment?
Let’s review some options
1 Forward-only projections with filters
1 Forward-only projections with filters
2 Sort - then - Apply events
1 Forward-only projections with filters
2 Sort - then - Apply events
3 Rebased Timelines with branches
1 Forward-only projections with filters
2 Sort - then - Apply events
3 Rebased Timelines with branches
too complicated
1 Forward-only projections with filters
2 Sort - then - Apply events
3 Rebased Timelines with branches
too complicated
not compliant with bigstreams of events
2 Sort - then - Apply events
3 Rebased Timelines with branches
too complicated
not compliant with bigstreams of events
1 Forward-only projections with filters
Challenge #4
How to provide multiple visions of the
same reality?

(operational - audit-trail)
Challenge #4
- 1 stream of events per aggregate instance
- We need to provide both an operational mode and an audit mode
t
Q: How to provide various points of view in our reality?
Thank you Greg!
2 projection modes
/ As AtAs Of "
/ As AtAs Of
As we should 

have known
"
/ As AtAs Of
As we should 

have known
Patches inside
"
/As Of
As we should 

have known
Patches inside
As At
As we knew
(at the time)
"
/ As At
As we knew
(at the time)
Audit trails
As Of
As we should 

have known
Patches inside
"
/ As At
As we knew
(at the time)
Audit trails
As Of
As we should 

have known
Patches inside
"
Since we have a model,
let’s find some exemples
Our main usages (patches included)
As Of - as we should have known
As Of - as we should have known
Imagine a stream of 3 events for a Fund
1.Let’s see how those events have been
saved over the time
As Of - as we should have known
t
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
As Of - as we should have known
t
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
As Of - as we should have known
t
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
2. Let’s do some As Of projections
event?
👎
Do NOT
Apply
👍
Apply
or
As Of - as we should have known
Name:

???
Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

???
Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

???
Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
???
Name:

Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
👍
Apply
Name:

“First name”
-pending-
Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“official name”“First name”
Projection date
Jun 1st 2017
???
Name:

“First name”
-pending-
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
👍
Apply
Name:

“Official name”
-pending-
“official name”“First name”
Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“Official name”
-pending-
“official name”“First name”
“patched name”
Projection date
Jun 1st 2017
???
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
👎
Do NOT
Apply
Name:

“Official name”
-pending-
“official name”“First name”
“patched name”
Projection date
Jun 1st 2017
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

“official name”
Projection date
Jun 1st 2017
Same events / another projection date
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

???
Projection date
Apr 1st 2016
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

???
Projection date
Apr 1st 2016
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
Name:

“First name”
-pending-
Projection date
Apr 1st 2016
???
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
👍
Apply
Name:

“First name”
-pending-
Projection date
Apr 1st 2016
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“First name”
-pending-
“official name”“First name”
Projection date
Apr 1st 2016
???
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“First name”
-pending-
“official name”“First name”
👎
Do NOT
Apply
Projection date
Apr 1st 2016
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“patched name”
-pending-
“official name”“First name”
“patched name”
Projection date
Apr 1st 2016
???
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“patched name”
-pending-
“official name”“First name”
“patched name”
👍
Apply
Projection date
Apr 1st 2016
As Of - as we should have known
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

“patched name”
Projection date
Apr 1st 2016
"
As At - as we knew (at the time) "
audit-trail use cases
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

???
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

???
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
Name:

Projection date
Apr 1st 2016
As At - as we knew (at the time) "
???
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
👍
Apply
Name:

“First name”
-pending-
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“First name”
-pending-
“official name”“First name”
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
???
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“First name”
-pending-
“official name”“First name”
👎
Do NOT
Apply
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“official name”“First name”
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
“patched name”
Name:

“First name”
-pending-
???
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“official name”“First name”
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
👎
Do NOT
Apply
“patched name”
Name:

“First name”
-pending-
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

“First name”
Projection date
Apr 1st 2016
As At - as we knew (at the time) "
Same events / another projection date
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

???
Projection date
Jun 1st 2017
As At - as we knew (at the time) "
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Name:

???
As At - as we knew (at the time) "
Projection date
Jun 1st 2017
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
Name:

As At - as we knew (at the time) "
???
Projection date
Jun 1st 2017
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name”
👍
Apply
Name:

“First name”
-pending-
As At - as we knew (at the time) "
Projection date
Jun 1st 2017
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“First name”
-pending-
“official name”“First name”
As At - as we knew (at the time) "
???
Projection date
Jun 1st 2017
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
Name:

“official name”
-pending-
“official name”“First name”
As At - as we knew (at the time) "
Projection date
Jun 1st 2017
👍
Apply
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“official name”“First name”
As At - as we knew (at the time) "
“patched name”
???
Projection date
Jun 1st 2017
Name:

“official name”
-pending-
t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“official name”“First name”
As At - as we knew (at the time) "
👎
Do NOT
Apply
“patched name”
Projection date
Jun 1st 2017
Name:

“official name”
-pending-
As At - as we knew (at the time) "
Projection date
Jun 1st 2017
Name:

“official name”t
Apr 1st

2016
Jan 1st

2016
Jan 1st

2017
Jun 1st

2017
“First name” “official name”
“patched name”
Still with me?
Challenge #5
How to produce a report for March 1st
like if we had made it June 1st?
Challenge #5
- We don’t want to suffer from hindsight bias
- We need to understand how we had perceived the world in the past
- We should not see some events that happened after a viewpoint
t
Q: How to produce a report for March 1st, like if we had
made it June 1st?
Name:

???
t
Q: How to produce a report for March 1st, like if we had
made it June 1st?
???
Feb 2nd

2016
Feb 1st

2016
Feb 28th

2016
March 1st

2016
Feb 3rd

2016
Jul 1st

2016
Jun 1st

2016
t
“name 1”
“name 2”
“name 5”
Feb 2nd

2016
Feb 1st

2016
Feb 28th

2016
March 1st

2016
Feb 3rd

2016
Jul 1st

2016
Jun 1st

2016
Q: How to produce a report for March 1st, like if we had
made it June 1st? Name:

???
???
t
Feb 2nd

2016
Feb 1st

2016
Feb 28th

2016
March 1st

2016
“name 1”
“name 2”
“name 5”
Feb 3rd

2016
Jul 1st

2016
Jun 1st

2016
Q: How to produce a report for March 1st, like if we had
made it June 1st? Name:

???
Date of the
report
Report
target date
t
Feb 2nd

2016
Feb 1st

2016
Feb 28th

2016
March 1st

2016
“name 1”
“name 2”
“name 5”
Feb 3rd

2016
Jul 1st

2016
Jun 1st

2016
Q: How to produce a report for March 1st, like if we had
made it June 1st?
Date of the
report
Report
target date
Apply all events created
before June 1st (viewPoint)
Don’t apply events created
after June 1st (viewPoint)
t
Feb 2nd

2016
Feb 1st

2016
Feb 28th

2016
March 1st

2016
“name 5”
Feb 3rd

2016
Jul 1st

2016
Jun 1st

2016
Q: How to produce a report for March 1st, like if we had
made it June 1st?
Date of the
report
Report
target date
Apply all events created
before June 1st (viewPoint)
“name 1”
“name 2”
Don’t apply events created
after June 1st (viewPoint)
t
Feb 2nd

2016
Feb 1st

2016
Feb 28th

2016
March 1st

2016
“name 5”
Feb 3rd

2016
Jul 1st

2016
Jun 1st

2016
Q: How to produce a report for March 1st, like if we had
made it June 1st?
Date of the
report
Report
target date
Apply all events created
before June 1st (viewPoint)
“name 1”
“name 2”
Don’t apply events created
after June 1st (viewPoint)
which bring us
2 new concepts
Viewpoint AsOfUntil

projection mode
Fund myFund = fundRepository.GetAsOUntil(fundId, projectedAt, viewPoint);
AsOf Until
Guid
March 1st

2016
June 1st

2016
In code we trust
?
Name1?
Name2?
Name5?
Challenge #6
Retroactive commands 

vs. Retroactive events?
Challenge #6
- Events are facts
- Commands are used to take decisions and to raise events
- Command may fail
t
Q: What should we do with ’retroactive’?
a) Apply a retroactive command to a aggregate
projected in the past? (may fail)
a) Apply a retroactive command to a aggregate
projected in the past? (may fail)
b) Create an event in the past for an aggregate?
a) Apply a retroactive command to a aggregate
projected in the past? (may fail)
b) Create an event in the past for an aggregate?
c) The answer C
c) There is no silver bullet
But we’ve mostly picked the option


a) Apply a retroactive command to a aggregate
projected in the past? (may fail)


so far
Challenge #7
Is U.T.C. enough?
tChallenge #7
- We store instants in our Event Store (createdAt, validFrom timestamps)
- Some events are applied on an entire “day” (e.g. June 8th)
t
Q: Which timestamps should we pick to describe a “day”?
Challenge #7
- We store instants in our Event Store (createdAt, validFrom timestamps)
- Some events are applied on an entire “day” (e.g. June 8th)
t
Q: Which timestamps should we pick to describe a “day”?
Q: Is UTC enough to store all instants?
Challenge #7
- We store instants in our Event Store (createdAt, validFrom timestamps)
- Some events are applied on an entire “day” (e.g. June 8th)
UTC [Utéçé;-)]

Universal Time Coordinated is the primary time standard by which the world
regulates clocks and time. It does not observe daylight saving time.
Instant [ˈÇaAriiiv]

Describes “when something happened”. Can then be interpreted in a
particular time zone and calendar system.
e.g.: 2018-05-18T16:40:35Z (Z means UTC, i.e. +00h)
Istanbul (+03)
What does June 8th even mean?
What does June 8th even mean?
Paris (+02)
Istanbul (+03)
UTC (+00)
Paris (+02)
Istanbul (+03)
What does June 8th even mean?
UTC (+00)
Jun 8th 2018
00h (+ 03h)
Paris (+02)
Istanbul (+03)
Jun 8th 2018
23h59 (+ 03h)
What does June 8th even mean?
UTC (+00)
Jun 8th 2018
00h (+ 03h)
Jun 7th 2018
21h (+ 00h)
Paris (+02)
Istanbul (+03)
Jun 8th 2018
23h59 (+ 03h)
Jun 8th 2018
21h59 (+ 00h)
What does June 8th even mean?
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 8th 2018
00h (+ 02h)
Jun 8th 2018
23h59 (+ 02h)
Jun 8th 2018
23h59 (+ 03h)
Jun 8th 2018
21h59 (+ 00h)
Jun 8th 2018
00h (+ 03h)
Jun 7th 2018
21h (+ 00h)
What does June 8th even mean?
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 8th 2018
00h (+ 02h)
Jun 7th 2018
22h (+ 00h)
Jun 8th 2018
23h59 (+ 02h)
Jun 8th 2018
21h59 (+ 02h)
Jun 8th 2018
23h59 (+ 03h)
Jun 8th 2018
21h59 (+ 00h)
Jun 8th 2018
00h (+ 03h)
Jun 7th 2018
21h (+ 00h)
What does June 8th even mean?
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 7th 2018
22h (+ 00h)
Jun 8th 2018
21h59 (+ 02h)
Jun 8th 2018
21h59 (+ 00h)
Jun 7th 2018
21h (+ 00h)
Event 1 ?
Should event 1 be involved in a June 8th projection?
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 7th 2018
22h (+ 00h)
Jun 8th 2018
21h59 (+ 02h)
Jun 8th 2018
21h59 (+ 00h)
Jun 7th 2018
21h (+ 00h)
Event 1?
only if it’s June 8th - Paris time
June 8th Paris !!= June 8th Istanbul
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 7th 2018
22h (+ 00h)
Jun 8th 2018
21h59 (+ 02h)
Jun 8th 2018
21h59 (+ 00h)
Jun 7th 2018
21h (+ 00h)
June 8th Paris time !!= June 8th Istanbul time
UTC Time is mandatory to store & compare events
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 7th 2018
22h (+ 00h)
Jun 8th 2018
21h59 (+ 02h)
Jun 8th 2018
21h59 (+ 00h)
Jun 7th 2018
21h (+ 00h)
UTC is mandatory but not enough
UTC (+00)
Paris (+02)
Istanbul (+03)
Jun 7th 2018
22h (+ 00h)
Jun 8th 2018
21h59 (+
02h)
Jun 8th 2018
21h59 (+
00h)
Jun 7th 2018
21h (+ 00h)
We need UTC Time + time zone of the event
time zone of the event?
Time zone of the action
that originated the event?
time zone of the event?
Time zone of the action
that originated the event?
Time zone associated with
the topic (i.e. a Fund)?
time zone of the event?
- Wrap up -
Discovering the unknown
Without concrete examples and a
model, you’re dead.
And more than ever…
y.a.g.n.i
you ain’t gonna need it
Would you
d a r e t o
destroy it?
OVER
ENGINEERING
is an embarrassment
to ourselves
Get prepared
to Design
BREAK
THROUGH
Thank you!
(White paper ongoing)

@tpierrain (use case driven)
Thank you!
And the
winner is…
?
7 SPEAKERS, 5 TALKS ORIGINAUX DE 15-20 MIN
EN QUOI NOUS INTÉRESSER AUX PROBLÈMES DU
MÉTIER NOUS A RENDU PLUS EFFICACE
LE MARDI 26 JUIN, CHEZ
DOMAIN FROM THE TRENCHES
Appendix
As At #2
As At #2 - as we knew at the time
As At #2 - as we knew at the time
As At #2 - as we knew at the time
“Patched name” will be <<discarded>> by the
following FundRenamed event
As Of #2
As Of #2 - as we should have known
“Patched name” is not <<discarded>> by the
following FundRenamed event (“official name”)
As Of #2 - as we should have known
But then it is replaced by the new one
( “OfficialName”)
You want to be ahead of what is done in software?
You understand there are bigger issues than just coding
We are looking for people who are daring, curious, sharing,
but who especially like team work
recruits
As time goes by (episode 2)
As time goes by (episode 2)

As time goes by (episode 2)

  • 1.
    As time goesby… Episode 2: technical challenges of bi-temporal Event Sourcing @tpierrain t
  • 2.
    If you want towin… Tweet like hell on… #newCrafts
  • 4.
  • 5.
  • 6.
    REQUIREMENTS — Understand their formerdecisions Fix their perception of the world retroactively
  • 7.
    REQUIREMENTS — Understand their formerdecisions Fix their perception of the world retroactively (Re)produce reports in and from the past
  • 8.
    REQUIREMENTS — Understand their formerdecisions Fix their perception of the world retroactively (Re)produce reports in and from the past Forecast ”events” in the future

  • 9.
    REQUIREMENTS — Understand their formerdecisions Fix their perception of the world retroactively (Re)produce reports in and from the past Forecast ”events” in the future
 Strong audit trail
  • 10.
    They needed atime machine
  • 11.
  • 12.
  • 13.
    Remember your bankingaccount? Event Sourcing
  • 14.
  • 15.
    Final state ofthe world All changes since 
 the beginning
  • 16.
    All changes sincethe beginning = A list of events
  • 17.
    Event [ɪˈvent] Describes afact, something that have happened. Usually expressed in a past-tense form.
 (e.g.: TalkStarted)
  • 18.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Event-Sourced business objects
  • 19.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Properties / Members Event-Sourced business objects
  • 20.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Evolution functions Change state Event-Sourced business objects
  • 21.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Constructor Change state Event-Sourced business objects
  • 22.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Decision functions Don’t change state Event-Sourced business objects
  • 23.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Event-Sourced business objects
  • 24.
    public class Fund: EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Decision functions Don’t change state Event-Sourced business objects
  • 25.
    Event-Sourced business objects publicclass Fund : EventSourcedAggregate { public Guid Id { get; private set; } public string Name { get; private set; } public Fund(IEnumerable<Event> events) { foreach(var evt in events) { Apply(evt); } } private Apply(FundRenamed event) { this.Name = event.FundNewName; } public IEnumerable<Event> Rename(string newName) { !// business logic and invariants checks HERE !// Raise event(s) return new[] { new FundRenamed(this.Id, newName) }; } } Decision functions Don’t change state Evolution functions Change state
  • 26.
    Projection [prəˈjekSHən] Deriving acurrent state from a stream of events
  • 27.
    Fund myFund =fundRepository.GetById(fundId, projectedAt); Event-Sourcing in motion Guid timestamp
  • 28.
    Fund myFund =fundRepository.GetById(fundId, projectedAt); Now b7f3ddfb-2cb5…. Event-Sourcing in motion
  • 29.
  • 30.
    t FundCreated
 “super yield ” Jan1st
 2016 Fund id: b7f3ddfb -2cb5…. Name: super yield Creation date: Jan 1st 2016 Management Company: Shares: Event-Sourcing in motion
  • 31.
    t Jan 1st
 2016 ManagementCompanyAssigned
 “BNP” Jan 30th
 2016 Fund id:b7f3ddfb -2cb5…. Name: super yield Creation date: Jan 1st 2016 Management Company: BNP Shares: Event-Sourcing in motion
  • 32.
    t Jan 1st
 2016 Jan 30th
 2016 FundRenamed
 “Yield2k22” Apr 1st
 2016 Fund id: b7f3ddfb -2cb5…. Name: Yield 2k22 Creation date: Jan 1st 2016 Management Company: BNP Shares: Event-Sourcing in motion
  • 33.
    t Jan 1st
 2016 Jan 30th
 2016 Apr1st
 2016 ShareAdded
 “Part D” Jun 2nd
 2016 Fund id: b7f3ddfb -2cb5…. Name: Yield 2k22 Creation date: Jan 1st 2016 Management Company: BNP Shares: Part D Event-Sourcing in motion
  • 34.
    Fund id: b7f3ddfb -2cb5…. Name:Yield 2k22 Creation date: Jan 1st 2016 Management Company: BNP Shares: Part D End of Stream >> <<t Jan 1st
 2016 Jan 30th
 2016 Apr 1st
 2016 Jun 2nd
 2016 Event-Sourcing in motion
  • 35.
    Projected at now Readyto work Fund id: b7f3ddfb -2cb5…. Name: Yield 2k22 Creation date: Jan 1st 2016 Management Company: BNP Shares: Part D
  • 36.
    The beauty ofit Pick the projection date you want ;-)
  • 37.
    Project same Fundat Apr 1st 2016 (same stream of events) Event-Sourcing in motion
  • 38.
  • 39.
    t FundCreated
 “super yield ” Jan1st
 2016 Fund id: b7f3ddfb -2cb5…. Name: super yield Creation date: Jan 1st 2016 Management Company: Shares: Event-Sourcing in motion
  • 40.
    t Jan 1st
 2016 ManagementCompanyAssigned
 “BNP” Jan 30th
 2016 Fund id:b7f3ddfb -2cb5…. Name: super yield Creation date: Jan 1st 2016 Management Company: BNP Shares: Event-Sourcing in motion
  • 41.
    t Jan 1st
 2016 Jan 30th
 2016 FundRenamed
 “Yield2k22” Apr 1st
 2016 Fund id: b7f3ddfb -2cb5…. Name: Yield 2k22 Creation date: Jan 1st 2016 Management Company: BNP Shares: Event-Sourcing in motion
  • 42.
    t Jan 1st
 2016 Jan 30th
 2016 Apr1st
 2016 Fund id: b7f3ddfb -2cb5…. Name: Yield 2k22 Creation date: Jan 1st 2016 Management Company: BNP Shares: We’re done here ;-) >> << Event-Sourcing in motion
  • 43.
    Command [kəˈmɑːnd] Triggers anaction. Modify the state of the system e.g.: RenameFund
  • 44.
    Commands are usedto take decisions and to raise events.
  • 45.
    Commands are usedto take decisions and to raise events. Command (RenameFund) Aggregate (Fund X)
  • 46.
    Commands are usedto take decisions and to raise events. Command (RenameFund) Events (FundRenamed) Events are used to restore/change the state of our aggregates. Aggregate (Fund X)
  • 47.
    so far sogood? 😉
  • 48.
  • 49.
    Challenge #1 How tochange what can’t be changed?

  • 50.
    Challenge #1 - Eventsare immutable (facts) - We save them in append-only streams (Event Store) t Q: How to retroactively change former mistaken events? Q: How to insert forgotten events in the past (in the middle of a stream)?
  • 51.
    we don’t changeevents we just add more events
  • 52.
    we don’t changeevents we just add more events
  • 53.
  • 54.
    “One more thing… Allour events have…”
  • 55.
    createdAt 

 validFrom !->when it applies 2 timestamps
  • 56.
    createdAt 

 validFrom !->when it applies 2 timestamps ( bi-temporal)
  • 57.
  • 58.
    Types of events validFrom createdAt Classicevent validFrom createdAt Retroactive event
  • 59.
    Thus we canhide former events
  • 60.
    Thus we canhide former events t Feb 1st
 2016 Feb 3rd
 2016 Feb 5th
 2016 “new naaame” “initial name”
  • 61.
    Thus we canhide former events t Feb 1st
 2016 Feb 3rd
 2016 Feb 5th
 2016 “new naaame” “initial name” “fixed name ;-)”
  • 62.
    Thus we canhide former events t Feb 1st
 2016 Feb 3rd
 2016 Feb 5th
 2016 “new naaame” “initial name” “fixed name ;-)”
  • 64.
  • 65.
    Challenge #2 - EventStore stores “Events” ;-) - Events are things that have already happened (facts) t Q: How to store things that have to happen in an Event Store?
  • 67.
    Let’s store ”aCommand (X) has just been Scheduled” events
  • 68.
  • 69.
  • 70.
    3 Types ofevents
  • 71.
    3 Types ofevents validFrom createdAt Classic event
  • 72.
    3 Types ofevents validFrom createdAt Classic event validFrom createdAt Retroactive event
  • 73.
    3 Types ofevents validFrom createdAt Classic event validFrom createdAt Retroactive event validFromcreatedAt “Command Scheduled” event C
  • 74.
  • 76.
    Challenge #3 How toproject unsorted streams of events?
  • 77.
    Challenge #3 - Withretroactive events, we have unsorted streams of events - Some events may hide others - Past may change at any time. Future too t Q: How to implement projections in such environment?
  • 78.
  • 79.
  • 80.
    1 Forward-only projectionswith filters 2 Sort - then - Apply events
  • 81.
    1 Forward-only projectionswith filters 2 Sort - then - Apply events 3 Rebased Timelines with branches
  • 82.
    1 Forward-only projectionswith filters 2 Sort - then - Apply events 3 Rebased Timelines with branches too complicated
  • 83.
    1 Forward-only projectionswith filters 2 Sort - then - Apply events 3 Rebased Timelines with branches too complicated not compliant with bigstreams of events
  • 84.
    2 Sort -then - Apply events 3 Rebased Timelines with branches too complicated not compliant with bigstreams of events 1 Forward-only projections with filters
  • 86.
    Challenge #4 How toprovide multiple visions of the same reality?
 (operational - audit-trail)
  • 87.
    Challenge #4 - 1stream of events per aggregate instance - We need to provide both an operational mode and an audit mode t Q: How to provide various points of view in our reality?
  • 88.
  • 89.
  • 90.
  • 91.
    / As AtAsOf As we should 
 have known "
  • 92.
    / As AtAsOf As we should 
 have known Patches inside "
  • 93.
    /As Of As weshould 
 have known Patches inside As At As we knew (at the time) "
  • 94.
    / As At Aswe knew (at the time) Audit trails As Of As we should 
 have known Patches inside "
  • 95.
    / As At Aswe knew (at the time) Audit trails As Of As we should 
 have known Patches inside "
  • 96.
    Since we havea model, let’s find some exemples
  • 98.
    Our main usages(patches included) As Of - as we should have known
  • 99.
    As Of -as we should have known Imagine a stream of 3 events for a Fund
  • 100.
    1.Let’s see howthose events have been saved over the time
  • 101.
    As Of -as we should have known t Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017
  • 102.
    As Of -as we should have known t Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name”
  • 103.
    As Of -as we should have known t Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name”
  • 104.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name”
  • 105.
    2. Let’s dosome As Of projections
  • 106.
  • 107.
    As Of -as we should have known Name:
 ??? Projection date Jun 1st 2017
  • 108.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 ??? Projection date Jun 1st 2017
  • 109.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 ??? Projection date Jun 1st 2017
  • 110.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” ??? Name:
 Projection date Jun 1st 2017
  • 111.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” 👍 Apply Name:
 “First name” -pending- Projection date Jun 1st 2017
  • 112.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “official name”“First name” Projection date Jun 1st 2017 ??? Name:
 “First name” -pending-
  • 113.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 👍 Apply Name:
 “Official name” -pending- “official name”“First name” Projection date Jun 1st 2017
  • 114.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 “Official name” -pending- “official name”“First name” “patched name” Projection date Jun 1st 2017 ???
  • 115.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 👎 Do NOT Apply Name:
 “Official name” -pending- “official name”“First name” “patched name” Projection date Jun 1st 2017
  • 116.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 “official name” Projection date Jun 1st 2017
  • 117.
    Same events /another projection date
  • 118.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 ??? Projection date Apr 1st 2016
  • 119.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 ??? Projection date Apr 1st 2016
  • 120.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” Name:
 “First name” -pending- Projection date Apr 1st 2016 ???
  • 121.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” 👍 Apply Name:
 “First name” -pending- Projection date Apr 1st 2016
  • 122.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 “First name” -pending- “official name”“First name” Projection date Apr 1st 2016 ???
  • 123.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 “First name” -pending- “official name”“First name” 👎 Do NOT Apply Projection date Apr 1st 2016
  • 124.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 “patched name” -pending- “official name”“First name” “patched name” Projection date Apr 1st 2016 ???
  • 125.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 Name:
 “patched name” -pending- “official name”“First name” “patched name” 👍 Apply Projection date Apr 1st 2016
  • 126.
    As Of -as we should have known t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 “patched name” Projection date Apr 1st 2016
  • 127.
  • 128.
    As At -as we knew (at the time) " audit-trail use cases
  • 129.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 Name:
 ??? Projection date Apr 1st 2016 As At - as we knew (at the time) "
  • 130.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 ??? Projection date Apr 1st 2016 As At - as we knew (at the time) "
  • 131.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” Name:
 Projection date Apr 1st 2016 As At - as we knew (at the time) " ???
  • 132.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” 👍 Apply Name:
 “First name” -pending- Projection date Apr 1st 2016 As At - as we knew (at the time) "
  • 133.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 Name:
 “First name” -pending- “official name”“First name” Projection date Apr 1st 2016 As At - as we knew (at the time) " ???
  • 134.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 Name:
 “First name” -pending- “official name”“First name” 👎 Do NOT Apply Projection date Apr 1st 2016 As At - as we knew (at the time) "
  • 135.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “official name”“First name” Projection date Apr 1st 2016 As At - as we knew (at the time) " “patched name” Name:
 “First name” -pending- ???
  • 136.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “official name”“First name” Projection date Apr 1st 2016 As At - as we knew (at the time) " 👎 Do NOT Apply “patched name” Name:
 “First name” -pending-
  • 137.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 “First name” Projection date Apr 1st 2016 As At - as we knew (at the time) "
  • 138.
    Same events /another projection date
  • 139.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 Name:
 ??? Projection date Jun 1st 2017 As At - as we knew (at the time) "
  • 140.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name” Name:
 ??? As At - as we knew (at the time) " Projection date Jun 1st 2017
  • 141.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” Name:
 As At - as we knew (at the time) " ??? Projection date Jun 1st 2017
  • 142.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “First name” 👍 Apply Name:
 “First name” -pending- As At - as we knew (at the time) " Projection date Jun 1st 2017
  • 143.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 Name:
 “First name” -pending- “official name”“First name” As At - as we knew (at the time) " ??? Projection date Jun 1st 2017
  • 144.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 Name:
 “official name” -pending- “official name”“First name” As At - as we knew (at the time) " Projection date Jun 1st 2017 👍 Apply
  • 145.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “official name”“First name” As At - as we knew (at the time) " “patched name” ??? Projection date Jun 1st 2017 Name:
 “official name” -pending-
  • 146.
    t Apr 1st
 2016 Jan 1st
 2016 Jan1st
 2017 Jun 1st
 2017 “official name”“First name” As At - as we knew (at the time) " 👎 Do NOT Apply “patched name” Projection date Jun 1st 2017 Name:
 “official name” -pending-
  • 147.
    As At -as we knew (at the time) " Projection date Jun 1st 2017 Name:
 “official name”t Apr 1st
 2016 Jan 1st
 2016 Jan 1st
 2017 Jun 1st
 2017 “First name” “official name” “patched name”
  • 148.
  • 150.
    Challenge #5 How toproduce a report for March 1st like if we had made it June 1st?
  • 151.
    Challenge #5 - Wedon’t want to suffer from hindsight bias - We need to understand how we had perceived the world in the past - We should not see some events that happened after a viewpoint t
  • 152.
    Q: How toproduce a report for March 1st, like if we had made it June 1st?
  • 153.
    Name:
 ??? t Q: How toproduce a report for March 1st, like if we had made it June 1st? ??? Feb 2nd
 2016 Feb 1st
 2016 Feb 28th
 2016 March 1st
 2016 Feb 3rd
 2016 Jul 1st
 2016 Jun 1st
 2016
  • 154.
    t “name 1” “name 2” “name5” Feb 2nd
 2016 Feb 1st
 2016 Feb 28th
 2016 March 1st
 2016 Feb 3rd
 2016 Jul 1st
 2016 Jun 1st
 2016 Q: How to produce a report for March 1st, like if we had made it June 1st? Name:
 ??? ???
  • 155.
    t Feb 2nd
 2016 Feb 1st
 2016 Feb28th
 2016 March 1st
 2016 “name 1” “name 2” “name 5” Feb 3rd
 2016 Jul 1st
 2016 Jun 1st
 2016 Q: How to produce a report for March 1st, like if we had made it June 1st? Name:
 ??? Date of the report Report target date
  • 156.
    t Feb 2nd
 2016 Feb 1st
 2016 Feb28th
 2016 March 1st
 2016 “name 1” “name 2” “name 5” Feb 3rd
 2016 Jul 1st
 2016 Jun 1st
 2016 Q: How to produce a report for March 1st, like if we had made it June 1st? Date of the report Report target date Apply all events created before June 1st (viewPoint) Don’t apply events created after June 1st (viewPoint)
  • 157.
    t Feb 2nd
 2016 Feb 1st
 2016 Feb28th
 2016 March 1st
 2016 “name 5” Feb 3rd
 2016 Jul 1st
 2016 Jun 1st
 2016 Q: How to produce a report for March 1st, like if we had made it June 1st? Date of the report Report target date Apply all events created before June 1st (viewPoint) “name 1” “name 2” Don’t apply events created after June 1st (viewPoint)
  • 158.
    t Feb 2nd
 2016 Feb 1st
 2016 Feb28th
 2016 March 1st
 2016 “name 5” Feb 3rd
 2016 Jul 1st
 2016 Jun 1st
 2016 Q: How to produce a report for March 1st, like if we had made it June 1st? Date of the report Report target date Apply all events created before June 1st (viewPoint) “name 1” “name 2” Don’t apply events created after June 1st (viewPoint)
  • 159.
    which bring us 2new concepts
  • 160.
  • 161.
    Fund myFund =fundRepository.GetAsOUntil(fundId, projectedAt, viewPoint); AsOf Until Guid March 1st 2016 June 1st 2016
  • 162.
  • 169.
  • 172.
    Challenge #6 Retroactive commands
 vs. Retroactive events?
  • 173.
    Challenge #6 - Eventsare facts - Commands are used to take decisions and to raise events - Command may fail t Q: What should we do with ’retroactive’?
  • 175.
    a) Apply aretroactive command to a aggregate projected in the past? (may fail)
  • 176.
    a) Apply aretroactive command to a aggregate projected in the past? (may fail) b) Create an event in the past for an aggregate?
  • 177.
    a) Apply aretroactive command to a aggregate projected in the past? (may fail) b) Create an event in the past for an aggregate? c) The answer C
  • 178.
    c) There isno silver bullet
  • 179.
    But we’ve mostlypicked the option 
 a) Apply a retroactive command to a aggregate projected in the past? (may fail) 
 so far
  • 181.
  • 182.
    tChallenge #7 - Westore instants in our Event Store (createdAt, validFrom timestamps) - Some events are applied on an entire “day” (e.g. June 8th)
  • 183.
    t Q: Which timestampsshould we pick to describe a “day”? Challenge #7 - We store instants in our Event Store (createdAt, validFrom timestamps) - Some events are applied on an entire “day” (e.g. June 8th)
  • 184.
    t Q: Which timestampsshould we pick to describe a “day”? Q: Is UTC enough to store all instants? Challenge #7 - We store instants in our Event Store (createdAt, validFrom timestamps) - Some events are applied on an entire “day” (e.g. June 8th)
  • 185.
    UTC [Utéçé;-)] Universal TimeCoordinated is the primary time standard by which the world regulates clocks and time. It does not observe daylight saving time.
  • 186.
    Instant [ˈÇaAriiiv] Describes “whensomething happened”. Can then be interpreted in a particular time zone and calendar system. e.g.: 2018-05-18T16:40:35Z (Z means UTC, i.e. +00h)
  • 187.
    Istanbul (+03) What doesJune 8th even mean?
  • 188.
    What does June8th even mean? Paris (+02) Istanbul (+03)
  • 189.
    UTC (+00) Paris (+02) Istanbul(+03) What does June 8th even mean?
  • 190.
    UTC (+00) Jun 8th2018 00h (+ 03h) Paris (+02) Istanbul (+03) Jun 8th 2018 23h59 (+ 03h) What does June 8th even mean?
  • 191.
    UTC (+00) Jun 8th2018 00h (+ 03h) Jun 7th 2018 21h (+ 00h) Paris (+02) Istanbul (+03) Jun 8th 2018 23h59 (+ 03h) Jun 8th 2018 21h59 (+ 00h) What does June 8th even mean?
  • 192.
    UTC (+00) Paris (+02) Istanbul(+03) Jun 8th 2018 00h (+ 02h) Jun 8th 2018 23h59 (+ 02h) Jun 8th 2018 23h59 (+ 03h) Jun 8th 2018 21h59 (+ 00h) Jun 8th 2018 00h (+ 03h) Jun 7th 2018 21h (+ 00h) What does June 8th even mean?
  • 193.
    UTC (+00) Paris (+02) Istanbul(+03) Jun 8th 2018 00h (+ 02h) Jun 7th 2018 22h (+ 00h) Jun 8th 2018 23h59 (+ 02h) Jun 8th 2018 21h59 (+ 02h) Jun 8th 2018 23h59 (+ 03h) Jun 8th 2018 21h59 (+ 00h) Jun 8th 2018 00h (+ 03h) Jun 7th 2018 21h (+ 00h) What does June 8th even mean?
  • 194.
    UTC (+00) Paris (+02) Istanbul(+03) Jun 7th 2018 22h (+ 00h) Jun 8th 2018 21h59 (+ 02h) Jun 8th 2018 21h59 (+ 00h) Jun 7th 2018 21h (+ 00h) Event 1 ? Should event 1 be involved in a June 8th projection?
  • 195.
    UTC (+00) Paris (+02) Istanbul(+03) Jun 7th 2018 22h (+ 00h) Jun 8th 2018 21h59 (+ 02h) Jun 8th 2018 21h59 (+ 00h) Jun 7th 2018 21h (+ 00h) Event 1? only if it’s June 8th - Paris time
  • 196.
    June 8th Paris!!= June 8th Istanbul
  • 197.
    UTC (+00) Paris (+02) Istanbul(+03) Jun 7th 2018 22h (+ 00h) Jun 8th 2018 21h59 (+ 02h) Jun 8th 2018 21h59 (+ 00h) Jun 7th 2018 21h (+ 00h) June 8th Paris time !!= June 8th Istanbul time
  • 198.
    UTC Time ismandatory to store & compare events UTC (+00) Paris (+02) Istanbul (+03) Jun 7th 2018 22h (+ 00h) Jun 8th 2018 21h59 (+ 02h) Jun 8th 2018 21h59 (+ 00h) Jun 7th 2018 21h (+ 00h)
  • 199.
    UTC is mandatorybut not enough UTC (+00) Paris (+02) Istanbul (+03) Jun 7th 2018 22h (+ 00h) Jun 8th 2018 21h59 (+ 02h) Jun 8th 2018 21h59 (+ 00h) Jun 7th 2018 21h (+ 00h)
  • 200.
    We need UTCTime + time zone of the event
  • 201.
    time zone ofthe event?
  • 202.
    Time zone ofthe action that originated the event? time zone of the event?
  • 203.
    Time zone ofthe action that originated the event? Time zone associated with the topic (i.e. a Fund)? time zone of the event?
  • 205.
  • 206.
  • 207.
    Without concrete examplesand a model, you’re dead.
  • 208.
  • 209.
  • 211.
    Would you d ar e t o destroy it?
  • 212.
  • 213.
  • 214.
  • 215.
    (White paper ongoing)
 @tpierrain(use case driven) Thank you!
  • 216.
  • 217.
  • 218.
    7 SPEAKERS, 5TALKS ORIGINAUX DE 15-20 MIN EN QUOI NOUS INTÉRESSER AUX PROBLÈMES DU MÉTIER NOUS A RENDU PLUS EFFICACE LE MARDI 26 JUIN, CHEZ DOMAIN FROM THE TRENCHES
  • 219.
  • 220.
  • 221.
    As At #2- as we knew at the time
  • 222.
    As At #2- as we knew at the time
  • 223.
    As At #2- as we knew at the time “Patched name” will be <<discarded>> by the following FundRenamed event
  • 224.
  • 225.
    As Of #2- as we should have known “Patched name” is not <<discarded>> by the following FundRenamed event (“official name”)
  • 226.
    As Of #2- as we should have known But then it is replaced by the new one ( “OfficialName”)
  • 229.
    You want tobe ahead of what is done in software? You understand there are bigger issues than just coding We are looking for people who are daring, curious, sharing, but who especially like team work recruits