Hi, Milan! I implement domain events in the domain layer project, the implementation you make is similar to the CQRS event handlers. I'm not an DDD expert, but the literature I studied suggest that domain events is used to save cross aggregate data. I have a aggregation root and I need to save someting in another aggregate root. One example could be the product balance and the balance history. If the logic is on domain layer, all projects that consume the domain services will have the same expected behavior. An endpoint or a background service that import invoices, for example, they both can use the same domain logic.
@@MilanJovanovicTech You have a point. We can use the application layer in other services as you designed. It's because I use domain events and events for different purposes, but the design you show is ok.
I've watch this and the outbox pattern, i have a question. Would you ever have a domain event that should cause the changes to ve rolled back? Or would you consider this part of the original database changes? In the outbox pattern you can't roll back, but in the second approach in this video you could potentially rollback if the database changes were inside a DB transaction.
GREAT VIDEO, I would love it if you create a video or post where you explain the difference between using Result Pattern to avoid exception and Global Exception Handler, which one is a better approach or depends on the project where we are using it or if we can use it both and how to... I hear someone that says Global Exception Handler is a bad practice and I disagree with that, but I would like to hear someone expert in those cases
Hi, one question, would it be a correct use of DomainEvents, if I had 2 types of events, those that have to be handled before calling SaveChanges, and those that will use the outbox pattern? As an example, i have some operations on entities/aggregate roots which "splits" them (thus creating new instances of entities in the domain layer) and I want to use DomainEvents to signal to the application that they have to be added to EF before saving changes Any hints maybe on where i could read about such scenario?
Hi Milan excellet content, my congratulations , sorry to bother you. Iam currently doing your course on clean architecture (the Bookify system), I have a question, on the domain project you create some share classes the currency and money. If for example my system needs to load all the currency for an external source (like an API or Database) how I can manage this ?? I have to create some king of interface in my domain ?? How I can still have something like this "public static readonly Currency Usd = new("USD"); public static readonly Currency Eur = new("EUR");"
Well, you can't - sadly. You'll have to load the currencies from the external source. :/ Unless you know ahead of time what the currencies will be - and you can hard code them. But this defeats the purpose of using that API.
Thank you very much for answering me, I imagined that it couldn't be done. So could I ask you one last question. If I am going to load the currecnys, for example, in a list, using the entity. Could the service that loads them (the interface) define it in the domain and implement it in the infrastructure or there is a better way@@MilanJovanovicTech
Hi Milan, why don't you use try/catch in the first process, so whenever something goes wrong in the publisher of the event it will not save the entity in the first process.
Hi Milan! I want to ask you, if we use the Outbox pattern approach you talked about before on the video you recommended us here, wouldn't be we publishing twice the domain events in the system? Because we are publishing them both in the Save changes async method and the background job that process outbox messages.
But when we use the approach to publish domain events AFTER saving the transaction, how can we make changes to the database (let's say that some domain event needs to change something in a different entity) reliably? I don't understand how this approach is more correct. It seems natural that domain events should be executed in the same transaction, because if one event fails, then everything is rolled back.
I separate domain (internal) events from integration (external) events. Domain events are part of the business transaction and should be ACID. Integration events are notifying external services. You could also invert the logic and use a listen-to-yourself pattern. Although both outbox and listen-to-yourself have issues. In both cases, your event handlers must be idempotent ie, make sure you handle the event exactly once.
@pilotboba Don't know what you mean by ACID in this case, but if you think that the effects of domain events should be saved in the same transaction as the change that triggered them, you will have a cascading effect all over your database, locking rows and pages everywhere, and then you have defeated the purpose of your aggregate design.
To be honest outbox pattern and using domain events like entity events or strict just aggragate root it doesn’t fell correct. I am not saying we should not use like this but they should be stored more global location in the bounded context. And publishing should only be done for going outside of the bounded context but firing async or synchronously should immediate maybe a static queue where a domain service manage it for extra control or logic for example uow should be fire an operation completed event instead of tracking micro events inside and publish them as a covering object instead of doing by a specific service contradicts separation of concern.
Is there a reason why you Follower is an aggregate? Why not just have a followers array field in the User aggregate? I'm going through the learning phase right now, so would love know why you have taken that approach.
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Outbox pattern is the only way to go. These two alternatives are no alternatives
I know that, leading into the Outbox solution
Hi, Milan! I implement domain events in the domain layer project, the implementation you make is similar to the CQRS event handlers. I'm not an DDD expert, but the literature I studied suggest that domain events is used to save cross aggregate data. I have a aggregation root and I need to save someting in another aggregate root. One example could be the product balance and the balance history. If the logic is on domain layer, all projects that consume the domain services will have the same expected behavior. An endpoint or a background service that import invoices, for example, they both can use the same domain logic.
Okay, I get what you're doing. Is that not true here?
@@MilanJovanovicTech You have a point. We can use the application layer in other services as you designed. It's because I use domain events and events for different purposes, but the design you show is ok.
I've watch this and the outbox pattern, i have a question.
Would you ever have a domain event that should cause the changes to ve rolled back?
Or would you consider this part of the original database changes?
In the outbox pattern you can't roll back, but in the second approach in this video you could potentially rollback if the database changes were inside a DB transaction.
I would never want to rollback in the domain event, no
I love your content, man.
Thanks a lot! 😁
GREAT VIDEO, I would love it if you create a video or post where you explain the difference between using Result Pattern to avoid exception and Global Exception Handler, which one is a better approach or depends on the project where we are using it or if we can use it both and how to...
I hear someone that says Global Exception Handler is a bad practice and I disagree with that, but I would like to hear someone expert in those cases
Combine these two:
1) th-cam.com/video/WCCkEe_Hy2Y/w-d-xo.html
2) th-cam.com/video/uOEDM0c9BNI/w-d-xo.html
Hi, one question, would it be a correct use of DomainEvents, if I had 2 types of events, those that have to be handled before calling SaveChanges, and those that will use the outbox pattern?
As an example, i have some operations on entities/aggregate roots which "splits" them (thus creating new instances of entities in the domain layer) and I want to use DomainEvents to signal to the application that they have to be added to EF before saving changes
Any hints maybe on where i could read about such scenario?
The first one sounds like something that's suitable for a domain service
Hi Milan excellet content, my congratulations , sorry to bother you. Iam currently doing your course on clean architecture (the Bookify system), I have a question, on the domain project you create some share classes the currency and money. If for example my system needs to load all the currency for an external source (like an API or Database) how I can manage this ?? I have to create some king of interface in my domain ?? How I can still have something like this "public static readonly Currency Usd = new("USD");
public static readonly Currency Eur = new("EUR");"
Well, you can't - sadly. You'll have to load the currencies from the external source. :/
Unless you know ahead of time what the currencies will be - and you can hard code them. But this defeats the purpose of using that API.
Thank you very much for answering me, I imagined that it couldn't be done. So could I ask you one last question. If I am going to load the currecnys, for example, in a list, using the entity. Could the service that loads them (the interface) define it in the domain and implement it in the infrastructure or there is a better way@@MilanJovanovicTech
Hi Milan, why don't you use try/catch in the first process, so whenever something goes wrong in the publisher of the event it will not save the entity in the first process.
If we wrap it in a transaction, yes
Hi Milan! I want to ask you, if we use the Outbox pattern approach you talked about before on the video you recommended us here, wouldn't be we publishing twice the domain events in the system? Because we are publishing them both in the Save changes async method and the background job that process outbox messages.
You don't publish them in SaveChangesAsync anymore - you only store them in the Outbox - and they're published later
@@MilanJovanovicTech Ok, thank you Milan! I'll implement it
But when we use the approach to publish domain events AFTER saving the transaction, how can we make changes to the database (let's say that some domain event needs to change something in a different entity) reliably? I don't understand how this approach is more correct. It seems natural that domain events should be executed in the same transaction, because if one event fails, then everything is rolled back.
Use an Outbox
Your intuition is correct - until you have domain events triggering soemthing other than the DB
I separate domain (internal) events from integration (external) events. Domain events are part of the business transaction and should be ACID. Integration events are notifying external services.
You could also invert the logic and use a listen-to-yourself pattern. Although both outbox and listen-to-yourself have issues. In both cases, your event handlers must be idempotent ie, make sure you handle the event exactly once.
@pilotboba Don't know what you mean by ACID in this case, but if you think that the effects of domain events should be saved in the same transaction as the change that triggered them, you will have a cascading effect all over your database, locking rows and pages everywhere, and then you have defeated the purpose of your aggregate design.
@@svorskemattias but what if the domain event handler fails? you now have a db in inconsistent state.
To be honest outbox pattern and using domain events like entity events or strict just aggragate root it doesn’t fell correct. I am not saying we should not use like this but they should be stored more global location in the bounded context. And publishing should only be done for going outside of the bounded context but firing async or synchronously should immediate maybe a static queue where a domain service manage it for extra control or logic for example uow should be fire an operation completed event instead of tracking micro events inside and publish them as a covering object instead of doing by a specific service contradicts separation of concern.
Depends on how you look at events. I use domain events "internally" and integration events when crossing bounded contexts
Is there a reason why you Follower is an aggregate? Why not just have a followers array field in the User aggregate? I'm going through the learning phase right now, so would love know why you have taken that approach.
How many followers do you plan to have? I have ~120k on LinkedIn for example. Do I want to store that in an array?