SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
Namasté ... come and meet BeauForma, the company you wished you worked for, and while you're at it, get an introduction in how to design, author and test projections for your next DDD/CQRS/ES project, hands-on. Bring a computer and pair up with a buddy.
Namasté ... come and meet BeauForma, the company you wished you worked for, and while you're at it, get an introduction in how to design, author and test projections for your next DDD/CQRS/ES project, hands-on. Bring a computer and pair up with a buddy.
12.
BUT, DUDE ... WE'RE
HERE FOR
PROJECTIONS,
REMEMBER?
13.
TERMINOLOGY
Event: a fact, something that happened, a message, a
datastructure
Stream: a sequence of events, partitioned by something
Event store: a collection of streams (simplified)
Disclaimer: not authoritive, just my take
17.
TERMINOLOGY
ProjectionHandler: a function that projects an event
Projection: a collection of handlers that form a unit
Projector: a function that dispatches an event or a batch
of events to the matching handler(s)
[Optional] ProjectionHandlerResolver: a function that
returns the handlers that match an event
Disclaimer: not authoritive, just my take
18.
EXAMPLE
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
open StackExchange.Redis
let inline (!>) (x:^a) : ^b =
((^a or ^b) : (static member op_Implicit : ^a > ^b) x)
let activeShoppersProjection (connection:IDatabase, message:Object) =
match message with
| :? GuestStartedShopping >
connection.StringIncrement(!> "ActiveShoppers", 1L) |> ignore
| :? GuestAbandonedCart >
connection.StringDecrement(!> "ActiveShoppers", 1L) |> ignore
| :? GuestCheckedOutCart >
connection.StringDecrement(!> "ActiveShoppers", 1L) |> ignore
| _ > ()
19.
EXAMPLE
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
public class ActiveShoppersProjection : ConnectedProjection<IDatabase>
{
public ActiveShoppersProjection()
{
When<GuestStartedShopping>((connection, message) =>
connection.StringIncrementAsync("ActiveShoppers"));
When<GuestAbandonedCart>((connection, message) =>
connection.StringDecrementAsync("ActiveShoppers"));
When<GuestCheckedOutCart>((connection, message) =>
connection.StringDecrementAsync("ActiveShoppers"));
}
}
20.
EXAMPLE
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
public interface IHandler<TMessage>
{
void Handle(IDatabase connection, TMessage message);
}
public class ActiveShoppersProjection : IHandler<GuestStartedShopping>,
IHandler<GuestAbandonedCart>, IHandler<GuestCheckedOutCart>
{
public void Handle(IDatabase connection, GuestStartedShopping message)
{
connection.StringIncrement("ActiveShoppers");
}
public void Handle(IDatabase connection, GuestAbandonedCart message)
{
connection.StringDecrement("ActiveShoppers");
}
public void Handle(IDatabase connection, GuestCheckedOutCart message)
{
connection.StringDecrement("ActiveShoppers");
}
}
31.
EXERCISE
Fill your datastructure using these events
- booking.fshttps://goo.gl/BTBTfi
32.
OBSERVATIONS
Not all events are useful,
Information might be missing from events,
Not all data is for viewing
Events challenge the datastructure
What about your observations?
33.
OBSERVATIONS
Not all data comes from one projection,
Not all data is owned by one model
34.
ONE EXTRA EVENT TO TAKE INTO ACCOUNT
1:
2:
3:
4:
5:
type GuestRegistered = {
GuestId : Guid;
FullName : string;
DateOfRegistration: DateTime;
}
35.
EXERCISE
Extend your projection with the event
- booking|guests.fshttps://goo.gl/BTBTfi
36.
POSSIBLE SOLUTION
1:
2:
3:
4:
5:
type GuestDocument = {
DocumentId: string;
GuestId: Guid;
FullName: string;
}
38.
EXERCISE
Express the projection in your language and store of choice
- booking|guests.fshttps://goo.gl/BTBTfi
39.
RECIPE?
define message types in code (for statically typed
languages)
define and implement projection handlers for each
message type
define and implement a dispatcher to those projection
handlers
test drive in the program's main