Your videos are helping me a lot. Those have the best explanations I have seen so far, I'm really starting to understand it. I haven't finished the course, you might answer these questions later, but I'll make them so I don't forget: Questions: 1. You're passing only the EmployeeId, but, let's say our business requires us to check if the Emploeey has permission to confirm an Order. Where/How would you make this permission check, since you're passing only the Id? 2. Your passing a "Products" object, which is a Collection of Product objects. Why aren't you passing an array (or Collection) of ProductId's? How do you know when you need to pass objects or just Ids? 3. Let's say you're running a SaaS, and using the same database for every Tenant, and the products table have a tenant_id. Where would you make the check that the Products passed to the Order actually belong to the correct Store (Tenant), for example? Maybe there's already an answer for these type of questions, if you have a video or content to recommend me, I'd appreciate it.
I don't think I'm going to be able to go in much depth with many of the questions, but I'll do my best to try to explain how I would think about them. I hope that I'm not too flippant about these concepts and send you in the wrong direction. I'm just unable to spend the time to consider them too deeply right now. 1. If you have a completely separate authorization system, then you don't have authorization events in your model. You simplify the Order model and you still can have employee ids communicating who made what changes, but a separate subsystem can handle authorization. There are many authorization frameworks you might even choose to use. 2. The Products type could just be an object that ensures that you've constructed a valid collection of Products. It could have convenience functions on it etc. In the code example linked in the description I seemed to have used an array. 3. Perhaps I would make it so that the Products are only ever loaded such that they're protected behind the correct tenant id. It's hard to say for me exactly how I might do this. But there ARE things you could do --for example-- include a tenant id in your event store (if that's relevant, I don't know), which would ensure that when loading event streams you're always limited to the correct tenant scope. I think you need to look at the various needs you meet and toy with the idea in order to find what's right for you.
@@ShawnMcCool thank you for the answer. And I wasn't expecting for a deeper explanation, I know this is a complex topic, this was already very helpful. What I got from your answer is that I can do those things is "several" different ways. I could have some Service that before building the Aggregate, let's say, placing the Order, makes all those check I talked about, and then the Order Aggregate is responsible only for the "Order" itself, meaning, it expects the data passed to it to already be "correct", because we know we used some "Middleware", for example, before reaching that code. So, about the correct Tenant data, I could assume, on my Domain code, that all data inside it has already passed through some Tenant check mechanism. I don't have to check it there. This would be specific to my use case. But for some other system, let's say, they might want to check Tenant inside a Aggregate... It all depends on the needs.
The arrow is when you call a method on an object. Like object.method() in another language. raise is a method that we built into the aggregate class that accepts and handles a new event.
19:15 The fulfill intention's invariant check for fulfilledBy should not be negated. @ShawnMcCool thank you for this excellent lesson and series!
Having never read about event sourcing before, after you revealed the body of the `rebuildFrom` method I was like "oh shit, that's sweet!"
Yeah fun stuff!
The state of an aggregate is a fold over the event stream.
Your videos are helping me a lot. Those have the best explanations I have seen so far, I'm really starting to understand it. I haven't finished the course, you might answer these questions later, but I'll make them so I don't forget:
Questions:
1. You're passing only the EmployeeId, but, let's say our business requires us to check if the Emploeey has permission to confirm an Order. Where/How would you make this permission check, since you're passing only the Id?
2. Your passing a "Products" object, which is a Collection of Product objects. Why aren't you passing an array (or Collection) of ProductId's? How do you know when you need to pass objects or just Ids?
3. Let's say you're running a SaaS, and using the same database for every Tenant, and the products table have a tenant_id. Where would you make the check that the Products passed to the Order actually belong to the correct Store (Tenant), for example?
Maybe there's already an answer for these type of questions, if you have a video or content to recommend me, I'd appreciate it.
I don't think I'm going to be able to go in much depth with many of the questions, but I'll do my best to try to explain how I would think about them.
I hope that I'm not too flippant about these concepts and send you in the wrong direction. I'm just unable to spend the time to consider them too deeply right now.
1. If you have a completely separate authorization system, then you don't have authorization events in your model. You simplify the Order model and you still can have employee ids communicating who made what changes, but a separate subsystem can handle authorization. There are many authorization frameworks you might even choose to use.
2. The Products type could just be an object that ensures that you've constructed a valid collection of Products. It could have convenience functions on it etc. In the code example linked in the description I seemed to have used an array.
3. Perhaps I would make it so that the Products are only ever loaded such that they're protected behind the correct tenant id. It's hard to say for me exactly how I might do this. But there ARE things you could do --for example-- include a tenant id in your event store (if that's relevant, I don't know), which would ensure that when loading event streams you're always limited to the correct tenant scope. I think you need to look at the various needs you meet and toy with the idea in order to find what's right for you.
@@ShawnMcCool thank you for the answer. And I wasn't expecting for a deeper explanation, I know this is a complex topic, this was already very helpful.
What I got from your answer is that I can do those things is "several" different ways. I could have some Service that before building the Aggregate, let's say, placing the Order, makes all those check I talked about, and then the Order Aggregate is responsible only for the "Order" itself, meaning, it expects the data passed to it to already be "correct", because we know we used some "Middleware", for example, before reaching that code.
So, about the correct Tenant data, I could assume, on my Domain code, that all data inside it has already passed through some Tenant check mechanism. I don't have to check it there. This would be specific to my use case. But for some other system, let's say, they might want to check Tenant inside a Aggregate... It all depends on the needs.
Nice work Shawn!
Great stuff on event sourcing tóopics! Puré gold!
Order seems like a finite state machine with events as inputs to change the state.
Everything is a state machine you're right. :)
Great Content. Thank you
Nice course, thanks!
I'm a bit confused, I don't understand PHP that much.
what does "->" and "raise" mean on line 6 at 5:11?
The arrow is when you call a method on an object. Like object.method() in another language. raise is a method that we built into the aggregate class that accepts and handles a new event.
amazing tutorial!!!
Thanks a lot! Great course! Keep it up!
best explanation
Thanks, I appreciate it mate!