Don't Make This Common Domain Events Mistake

แชร์
ฝัง
  • เผยแพร่เมื่อ 7 พ.ย. 2024

ความคิดเห็น • 33

  • @MilanJovanovicTech
    @MilanJovanovicTech  11 หลายเดือนก่อน +1

    Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
    Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt

  • @svorskemattias
    @svorskemattias 10 หลายเดือนก่อน +3

    Outbox pattern is the only way to go. These two alternatives are no alternatives

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 หลายเดือนก่อน

      I know that, leading into the Outbox solution

  • @RenatoGontijo
    @RenatoGontijo 11 หลายเดือนก่อน +2

    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
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Okay, I get what you're doing. Is that not true here?

    • @RenatoGontijo
      @RenatoGontijo 11 หลายเดือนก่อน

      @@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.

  • @IanWilkinson-SgtWilko
    @IanWilkinson-SgtWilko 10 หลายเดือนก่อน +1

    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.

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 หลายเดือนก่อน

      I would never want to rollback in the domain event, no

  • @whatinthebloodyhell
    @whatinthebloodyhell 11 หลายเดือนก่อน +5

    I love your content, man.

  • @checox1909
    @checox1909 11 หลายเดือนก่อน +1

    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

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +1

      Combine these two:
      1) th-cam.com/video/WCCkEe_Hy2Y/w-d-xo.html
      2) th-cam.com/video/uOEDM0c9BNI/w-d-xo.html

  • @unimatrix20a
    @unimatrix20a 8 หลายเดือนก่อน

    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?

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน +1

      The first one sounds like something that's suitable for a domain service

  • @orlandotorres1285
    @orlandotorres1285 10 หลายเดือนก่อน

    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");"

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 หลายเดือนก่อน

      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.

    • @orlandotorres1285
      @orlandotorres1285 10 หลายเดือนก่อน

      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

  • @irwanazamahmad3302
    @irwanazamahmad3302 2 หลายเดือนก่อน

    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.

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 หลายเดือนก่อน +1

      If we wrap it in a transaction, yes

  • @danilousuga410
    @danilousuga410 11 หลายเดือนก่อน

    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.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +1

      You don't publish them in SaveChangesAsync anymore - you only store them in the Outbox - and they're published later

    • @danilousuga410
      @danilousuga410 11 หลายเดือนก่อน

      @@MilanJovanovicTech Ok, thank you Milan! I'll implement it

  • @matthewrossee
    @matthewrossee 11 หลายเดือนก่อน +2

    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.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Use an Outbox

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Your intuition is correct - until you have domain events triggering soemthing other than the DB

    • @pilotboba
      @pilotboba 11 หลายเดือนก่อน

      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.

    • @svorskemattias
      @svorskemattias 10 หลายเดือนก่อน

      @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.

    • @matthewrossee
      @matthewrossee 10 หลายเดือนก่อน

      @@svorskemattias but what if the domain event handler fails? you now have a db in inconsistent state.

  • @bpostaci
    @bpostaci 6 หลายเดือนก่อน

    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.

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 หลายเดือนก่อน

      Depends on how you look at events. I use domain events "internally" and integration events when crossing bounded contexts

  • @yaminnather521
    @yaminnather521 11 หลายเดือนก่อน

    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.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +2

      How many followers do you plan to have? I have ~120k on LinkedIn for example. Do I want to store that in an array?