Lecture thumbnail 4:15 / 26:42 Seekers and event sourcing are both very simple, trivial concepts.

In actual fact, they’re very easy to understand.

There is absolutely no magic involved in them.

And on the other hand, the approach you might argue is a bit heavy handed compared to how we do it

in the real world.

So let’s imagine that you have a class called person, you’re modeling a human being.

Typically what you would do in the sort of domain model scenario, you would just give this person an

age, for example, as a property, and then you would go off and you would actually instantiate this

object directly.

So you say var P equals new person, and then you would say P dot age equals 123, whatever.

You could then print out P or PS age or whatever you want.

Okay.

The only problem is that at this point, I mean, like here you’ve, you’ve made a change and let’s

suppose that you want to track the change.

You want to remember that at some point you set the age to 123.

Now why would you want to track things?

Well, one reason is audits and, you know, a form of logging in the sense that you can track what

your what this particular field of property was set to.

That’s kind of like having a historical debugger, kind of like the Intel trace approach, very similar.

But the other thing is you might want to backtrack.

So you want to take your entire massive super complicated system and you want to take it back a couple

of hundred states or you want to take it back an entire day, maybe because you want to perform a rollback,

but maybe because you just want to investigate how you ended up with the values you ended up with.

And not having this information is really detrimental to fixing fixing systemic issues in your in your

services, in your applications, because you have no idea the exact set of circumstances which led

to a particular situation.

So two ideas related to this are one, which is command query responsibility, segregation.

Essentially the idea that a typical component does not communicate does not give you a direct interface

for changing something or getting something.

Instead, it receives a command or it receives a query and it responds on the basis of what it actually

received, or it might choose not to respond, for example.

And the other is event sourcing.

And the idea here is that all the changes, like, for example, the fact that you set a property to

123, all the changes are encapsulated as events.

And now the advantage, as I said, is that you can review and roll back and whatever and you want these

things to be serializable as well, which means that even though in this example I’m operating on references

to objects, really you would have objects which have unique identifiers which are themselves serializable,

You can persist the entire state of events plus the current object graph on whatever is in it.

So at any point in time you can take your system throughout its entire lifetime using event sourcing.

And this is great.

And this is what we’re going to take a look at from the from the c sharp perspective.

Now, what first of all, let’s talk about actors and the two different types of things that exist.

So command.

Command is when you want an object to do or change something.

So if I want to set the person’s age, I don’t say person dot age equals whatever.

This no longer works.

Instead, I send it a command, I send it a command saying, Can you please change your age?

And then it can change its age.

It can avoid changing its age.

Some other component can interfere in our sending of a command to person and cancel it or modify it.

For example, we could have a separate component, which when you sort of lie on your driver’s license,

it actually decreases your age by three.

And so the value you actually set is not the real value that was passed in because it was intercepted.

And stuff like that is generally, generally very easy to do if you adopt this approach.

So instead, person still has an age, so you still have a private field called age with a small A because

it’s private and you’re not really.

At no point in time will you be exposing it to anybody because you want to make it impossible to manipulate

the object directly.

And in fact, this reference shouldn’t exist either.

But we’re sort of we’re going to ignore this particular bit.

So what happens typically is that person as well as other objects in the system they would typically

have.

Communication organized through a centralized component.

I call this component an event broker.

Other people give it different kind of names.

So I like the I like the event broker notation.

So there are three things in the event broker.

So one is you have a set of all events that happened or you could have some time horizon of events.

So essentially or you could be serializing them, of course.

And the reason why you want all events is that when you want to backtrack to a particular state in the

system, you can do it easily.

And if you want to get back to where you were, you can do that easily.

If you want to backtrack and then forget all the changes and do a do a new branch, for example.

So you can have several branches of the development of your system, you can do that easily.

And the reason for that is that you essentially have a list of all the events.

I’m going to trivialize what’s actually a fairly complicated construct here, and I’m just going to

represent it as a list.

So you would essentially have something like a public list of event and event is something we’re going

to specify.

So I’ll call this all events equals new list of events.

There we go.

So event at the moment is just, you know, some, some type, some type with some type of polymorphism

on top of it.

So essentially we store all the things that happen, like for example, somebody changes person’s age.

That’s an event that gets stored, somebody removes an object, moves an object from location to location.

B that’s an event.

All of these things can be recorded.

And the critical thing about events is that you should really be able to backtrack.

So once an event happened and you recorded it from that event, you should reconstruct a command which

undos the event.

Assuming that the concept of undo is applicable because sometimes it really isn’t.

Okay.

So second thing is you want the commands to be able to be able to post commands on the broker to send

them to everybody basically.

And the third thing is you want queries.

And you want to be able to query, for example, ask the person, Well, can you tell me what your age

is, for example?

Okay, so we’re going to implement all of this now.

Now, obviously, event broker is something which is everywhere.

And since we we might have it as a static object, but we might also simply inject it as a constructor

parameter.

For example, if we assume that the event broker actually represents a system which kind of lives or

doesn’t live, then it makes sense to use dependency injection and just inject the entire thing.

So essentially you have event broker, broker like this and then you initialize it from the constructor.

That’s that’s a very simple approach.

So what happens then is you have something like you have your event broker and you would have just one

in the system, so it would have a singleton lifetime and then it would your dependency injection container

would automatically inject it to whatever objects are being created in the system.

Okay, So you’ve got an event broker.

And the goal of this whole thing is that you can listen to some of the changes because essentially when

somebody puts a command or a query, we want to notify the world basically.

And for that we use events because, well, in the real world, you can use events, you can use other

things like, well, there are lots of data structures for this exact thing.

So I’m going to have an event and let’s have an event.

Handler Okay.

So this event, it actually sends off a command.

So let’s just say command here and let’s call this commands, for lack of a better terminology.

I like repeating the same thing over and over.

So.

Uh, let’s make command.

So once again, this is just going to be a type.

And the same goes for the query event.

So whenever somebody wants some information, this goes through this event for queries.

So queries.

Okay, so query is also a type for now, right?

So we have two events and whenever somebody wants something, they have to basically invoke this event

and we can we can make helper functions.

In fact, we are going to make helper functions.

And our first concern is how to set the age of the person under this layout.

So to set the age of the person, we issue a command.

So a command is something that asks an object to do something or to change itself or to perform some

sort of action.

So in order to issue this command, we have to have some sort of API on the event broker for doing exactly

that.

I made things public here.

But in addition, let’s let’s just simplify things so that it becomes a bit more clearer.

So let’s suppose that you want to generally query for, well, no, we’re not doing queries yet, so

you want to just invoke a command.

So you would have a method called command which would take a command.

Let’s have see.

And what would happen is you say commands invoke this comma.

See?

That’s it.

That’s how you would do.

You invoke the command and off it goes.

So we want to send p the person a command for changing the age.

How do we do it?

Well, we already have a mechanism for invoking the command, but nobody’s really listening to it because

person has to be listening to this command in order to react to it.

So essentially, we say broker dot commands and then we create a method broker on commands.

So what do we do here?

Well, we’re getting some command, but really person has to specify what kind of commands it can.

It can really process.

So for example, you might have a change age, command, change, age, command, all right, So let’s

suppose that our commands are targeted so they they would target a specific person.

For example, let’s actually do this in here in the change age command.

So we’ll leave the base class as it is.

Well, you might want to have it as event args for no reason whatsoever and you might also here specify

who you’re changing.

So you specify the person who is the target of this change and in addition you specifying the new value,

so you specifying the new age that you want to set.

So I made a constructor here as well.

So what happens when we want to actually change?

This is we say event broker, dot

command, New Change Age command.

The target is P and the age is 123.

So does it work?

I mean, let’s let’s find out.

Let’s write p dot.

We don’t have age.

That’s right.

We can’t get age, you see, because that’s something that we encapsulated.

It’s private.

You can’t get it.

So now the question is, well, what happens when somebody sends this command?

So first of all, you change, whether it’s the change age command, var CAC equals command as CAC.

So if CAC is not equal, actually you can do it this way.

So we we now check the what we what do we do now?

Let me just think.

Yeah.

So we need to make sure that the command is not null.

And we also need to make sure that the target is this.

So if CAC is not equal to null and CAC dot target is equal to this, then we can actually do something.

Then we can change the age.

So we say age equals age with a small a equals CAC dot age.

There we go.

Okay, So this this would it would appear as though this is all you need to do.

So we now have the command part done.

Now about the query part, how do you get the age?

And here, of course, you subscribe to yet another event.

So whenever somebody sends a query for something, then once again, we need more classes.

As it happens.

So we have age query.

Somebody wants the age.

Okay.

So we can process that.

So we can say var AC equals query as age query.

And once again, when you send the query, you might want to specify who the target is.

So you might want to say public person target, and only if the target if AC is not equal to null and

AC dot target equals this.

Only then do you set the return value.

Now notice it’s a void here.

So the way to return something for a query is to set it somewhere.

So you might have something like this and this could be a bit painful, I guess, because I’m going

to do object result.

Okay, So object obviously means that you’re boxing and it all becomes really nasty and you have to

have the name, the type of the function in the invocation, which is annoying.

But the end result is that when you query, you say AC dot result equals H.

There we go.

That’s all you need to do.

So that’s how the query works and we can try it straight away.

But in order to try it we might want to have another helper function inside the event broker and this

time we can do a bit of magic with generics just to make it a bit more palatable.

So we’re going to have a return type T query of T, so we specify some query and then we invoke it.

So queries invoke this comma command.

Oh, it’s Q actually.

And then what we do is we return Q dot result, but we need to cast it to T All right.

So now we can get the age using this approach so we can say int age equals int age equals event broker

dot query query for an int and then specify the the actual query.

So here instead of P, what we specify is a new age query.

And let’s, let’s see what we need to specify target equals P There we go.

Okay, so do we have no.

So let’s see if this actually works.

Let’s see if we can get it to work.

I’m just going to run this.

Yes.

123 So we set the, we set the element and we got it.

So that shows.

What about event sourcing?

Well, at the moment nobody’s really tracking these changes.

Somebody said the age and then they said it again and nobody’s really tracking it.

You can see all events thing is not being used, so let’s actually use it.

Let’s record every single change so that we can backtrack it.

Okay.

So for that we use yet another hierarchy.

We have a hierarchy called event.

And by the way, let me let me open up the file structure Explorer so you can see the structures that

we’re using.

You can see lots of structures and lots of members here.

So event.

Okay.

So this is a base class.

Actually, I think we already have one.

Yeah, we already have an event somewhere.

So now all we have to do is make a derive type.

So let’s suppose the age changes so we can call this age changed event or just age changed whatever.

What do we need to store about this event?

Well, we might want to store the target person Target and we want to store the all the new values.

So public int old value and new value.

And then well, I think that’s, that’s pretty much it.

We might want to have a constructor for all of this and that’s, that’s all we’re done.

So now immediately before we perform the actual change, so when we handle the command for changing

the age, before we assign the actual age, we send an event.

So for example, we say that broker dot events, dot add new age changed event this then the old value

which is age, then CAC dot age.

There we go.

So now what we’re doing is we’re essentially recording the fact that we set the age to some value and

this is great.

This, this is actually we can we can print out all the events as they happen.

So let me let me find this event.

The change aged, not the command, the actual event.

And then what we can do is we can do a to string and here I can say return age changed from old value.

To a new value.

There we go.

Extra semicolon here or curly brace, rather.

Okay, so after this change, we can print out each event for each of our E in ab dot.

All events keeping it public at the moment.

Console dot write line.

E actually, don’t we have don’t we have for each?

No, I wish we did.

I wish we did have for each.

Okay, so if I run this, you’re going to see that here we now registered this change so h changed from

0 to 123.

So that’s good.

Now the final kind of the icing on the cake, how could we undo something?

Because now we’re keeping every change in the system so we can restore the system to virtually any state

that we want.

And if you implement serialization properly, then you should be able to serialize these and create

branches and whatever.

So how do we let’s do a simple undo.

So inside the broker, I’m going to have a method for undoing the last operation undo last.

So the goal of this undo last is that you essentially look at the last event.

And then you say, well, if this is h changed so AC equals e as h changed.

And if this is not equal to null, then what you do is you invoke a command for reversing this change.

Because remember, you cannot communicate with components directly.

You can only do commands ever.

So you invoke the command, you change h command, and here you specify the target, AC dot target.

But the value you want to set is the old value, not the new value.

Okay?

And then of course you remove the event because it never happened.

Uh, AC or no, just all events.

Remove.

Remove the event.

E There we go.

So you might think this is correct, but not really.

There’s one more problem.

So let’s imagine that after I perform the change and I print the age.

So let’s have, uh, can we separate split declaration and assignment?

Because after I print this, what I do is I perform an undo undo last.

And then if I print all the events.

How are you going to see that?

I changed the age from 0 to 123, and then I have a different event.

Like I changed the age from 123 to 0, which is incorrect because if I wanted to undo, I wanted to

get rid of all the events.

I don’t want to generate a second event.

So for that we use suppression.

So effectively you suppress the fact that the change actually occurred.

So if we go to the command class, what we can do is we can say boo register equals true.

So by default, commands are registered, they generate events.

But in certain cases, like when you perform the undo, you might want to suppress it.

So if you want to undo something, then you really want to specify that you don’t want to register.

So I say register equals false.

And then of course, up here, when when the command gets generated, you say if and only if you want

to register the command, then you actually perform the notification.

So as we run this, you’ll see h changed from 0 to 123.

But after we undo, there is nothing more to print because we undid all the changes in the system.

And now let’s just, just for the sake of completion, let me show you that we did in fact undo the

whole thing.

So I’ll do this once again.

And we have zero.

So we change the age from 0 to 123 Here it is.

And then we undid it to the default value and it’s now zero.

So this is a small overview of how you would do an event sourcing in net.

There are lots of issues with this entire approach.

So let me let me show you some of them.

One issue is that the at the moment there is no modeling of dependent properties.

So for example, if I write Publicbool can vote and can vote is going to be defined as a property which

returns true if the age if the small age is greater than or equal to 16, then there is no way for us

to model the dependency between age and can vote.

And we are a bit stuck once again because well, we have to have additional mechanisms for specifying

that.

Another issue is that these events are not weak, so you kind of you subscribe to them, but what if,

you know, person goes out of scope or whatever, You’re not really controlling this properly.

And in fact, instead of the simpler, simple event broker that we’re using here, I prefer a reactive

extensions event broker which is much smarter and can essentially the thing with reactive extensions,

event broker is the subscription is disposable, so you can put it inside a using or something and,

and it’s very useful.

And of course, the other thing, as I mentioned, is you typically don’t provide references when you

send things on the wire.

So you would in the real world, what would typically happen is you would have some sort of person pool

or person storage and then you would have maybe a dictionary from some unique ID to person like this

people.

And then what you would have inside a person is you would have a public int unique ID, So every object

which is created would not you wouldn’t be able to create an object using the constructor like this.

Instead you would generate it and it would generate a unique ID, and these unique IDs would have all

the objects in a particular form of storage.

And the advantage of that is that you now get serialized properly serializable events because this I

don’t know how to serialize it, to be honest.

What you should be able to do is you should be able to serialize target ID, target ID, you should

be able to serialize that and serializing reference is a bit weird.

So that’s how you do it in the real world and that’s how you end up with systems which you could certainly

do in in C sharp, but you can equally implement this whole thing in C or C plus plus or any other language

which doesn’t have events and that sort of thing.

So this has been a small demo and let me know if you have any questions if this is of interest to you.

So thanks for watching and bye bye.

Play Play Play Play Play Play Play information alert