Using Domain Events To Build A Decoupled System The Scales

Поделиться
HTML-код
  • Опубликовано: 8 сен 2024

Комментарии • 93

  • @MilanJovanovicTech
    @MilanJovanovicTech  Год назад

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

  • @majormartintibor
    @majormartintibor Год назад +12

    Milan I am really looking forward to a full course from you, building an entire application with DDD, Rebus, RabbitMQ etc etc.
    I hope you will make one!
    Great video btw!

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +9

      It's coming in a few months! :)
      Starting recording May/June

    • @rohit704
      @rohit704 Год назад +1

      Thanks for asking , I was looking the same :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +3

      @majormartintibor Course is nearly ready, coming out in a few weeks. I'm calling it "Pragmatic Clean Architecture"

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      @@rohit704 Coming out soon, pay attention to my newsletter for the launch

  • @rustamhajiyev
    @rustamhajiyev Год назад +6

    Speaking about trying to saving entity and domain events together, that is why I prefer using event sourcing :) you deal only with domain events and rebuild entities based on them.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +2

      If only it were as beautiful as it sounds 😅 There are many nuances with event sourcing that can be easily overlooked.

    • @rustamhajiyev
      @rustamhajiyev Год назад

      @@MilanJovanovicTech of course, it's not a silver bullet :)

    • @alexisnarvaez
      @alexisnarvaez 3 месяца назад

      @@MilanJovanovicTech But man, please, beare with me. You are telling your audience to store events with EF Core and then develop a full backround service that polls for events tand tries to publish somewhere else... how is that easier than simple go event sourced and use something like EventStoreDB to handle persistence, and subscription of events?

  • @eser-sahin
    @eser-sahin Год назад +3

    Clean and simple implementation, thanks for sharing with us.

  • @user-zm2dh8uz6p
    @user-zm2dh8uz6p Год назад +2

    Hey Milan, really nice video. I'm looking forward for this new robust impl of the outbox pattern. Thanks for making such an awesome content, free.

  • @juancamiloromerosarmiento2711
    @juancamiloromerosarmiento2711 10 месяцев назад +2

    You are the best man ... !! learning a lot from this collection of videos !! I feel my self like an expert in DDD ... hahaha

  • @alan-
    @alan- Год назад +1

    I'm really liking your videos. Always clear and concise.

  • @robertmrobo8954
    @robertmrobo8954 Год назад +1

    Looking forward to an indepth Outbox Pattern video. ❤

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Recording it soon 😁

    • @MJ-yx4ut
      @MJ-yx4ut Год назад

      @@MilanJovanovicTech What will the difference be against your previous video about Outbox Pattern?

  • @adriano.digiere
    @adriano.digiere Год назад +3

    Hi Milan! Great video.
    Is there any video in which you talk about integration events?
    Thanks for the content.

  • @OscarAgreda
    @OscarAgreda 21 день назад

    Thank you for the insightful breakdown of domain events and their role in decoupling systems! I’m curious about your thoughts on the Outbox pattern versus traditional transactional methods, particularly in terms of scalability and complexity in distributed systems. How would you approach balancing these trade-offs in a large-scale microservices architecture?

    • @MilanJovanovicTech
      @MilanJovanovicTech  21 день назад

      The Outbox is there for temporal decoupling and reliably publishing messages - both of these are helpful in improving the scalability of a service.

  • @empireofhearts
    @empireofhearts Год назад +3

    After watching couple times, im still left with impression that nothing changed from start to end, we are still raising event after we saved changes to the DB except at start, specific event was raised in domain layer probably scattered and at end all events are raised by iterating events in the persistence/infrastructure layer. at both times we would throw any exception in the events back to the UI/calling layer. Am i missing something? Effectively the title of the video is achieved in a way but the drawback still exist. i think the drawback is true for any in memory event bus.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Yes, there's that drawback you noticed with this implementation. The Outbox pattern solves that issue

    • @empireofhearts
      @empireofhearts Год назад

      @@MilanJovanovicTech thank you for the information. so you planning to show that in coming in upcoming video?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      @@empireofhearts Yes 😁

  • @alexmadnix
    @alexmadnix Год назад +1

    TQ Milan^^ 14:01

  • @pabloferrando6471
    @pabloferrando6471 Год назад +2

    Hi, Milan! This is clear for use cases where you invoke methods on the aggregate root, such as create() or addItem(), where you can publish the corresponding event inside the entity producing it, but how would you approach an OrderDeletedEvent? Would you need to pass through a delete() method or something alike?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      Yeah, that would get the job done. Just expose a method that raises an event inside.

  • @andersjuul8310
    @andersjuul8310 Год назад +2

    Hi Milan, perfect timing; I was just introducing DomainEvents to an otherwise Clean Architecture yesterday. Pretty much as you present it. However, a consideration: One of my events is change of State and I was debating with myself whether I should have a StateChangedDomainEvent or multiple like StateChangedToAuthorized, StateChangedToTerminated etc. I guess "it depends", but do you have any thoughts you'd like to share?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +4

      I'd say it depends on how you handle it?
      Also, the State is obviously a part of a larger object/entity/aggregate.
      Maybe OrderState? So it should be OrderAuthorized/OrderTerminated more so than StateChanged

  • @remcobrosky1018
    @remcobrosky1018 Год назад +1

    Really like your content and views on real world architectural challenges.
    Isn”t this specific approach creating a dependency on MediatR in your domain model? I consider this a framework dependency that I would avoid.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Yes, but it's a tradeoff I'm willing to make for the benefit of simplicity

  • @nove1398
    @nove1398 Год назад +1

    Lesser of two evils Indeed, i prefer the approach that is after and as some clean up

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      There's a way to fix though

    • @nove1398
      @nove1398 Год назад

      @@MilanJovanovicTech will there be a video on that? Or did you already have the video posted?

  • @josecarlosmacoratti
    @josecarlosmacoratti 6 месяцев назад

    Create your DomainEvent implementing INotification makes the Domain tightly coupled to MediatR and any changes to MediatR affect your domain and I think it is not a good practice but I could be wrong

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 месяцев назад

      I prefer being practical rather than dogmatic.
      What could possibly change with MediatR? Will pub-sub become unpub-unsub? (sorry for being ironic, but 😅)

  • @chrismingay6005
    @chrismingay6005 Год назад +1

    Very clear video as always, thank you! Generally speaking would it be better to not pass the cancellation token to _publisher.Publish ? By that I mean if the system has got as far as saving the changes to the database we do not want to allow it to back out of publishing the domain events.

  • @ramytawfik9168
    @ramytawfik9168 Год назад +1

    Can you please milan make a video about Threading , async and await and Parallel and multi-threading if you have time.
    And Thanks for all your effort

  • @Andy01010
    @Andy01010 Год назад +3

    Btw water to ask, do you use domain events to communicate between aggregates much?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +2

      Yes, it's very powerful for triggering side effects within a bounded context

  • @lourenceplay9017
    @lourenceplay9017 7 месяцев назад

    Great video, thanks!
    Will there be more videos with the development of the E-shop web api? And will you add any new entities to the project? Product cart for example

  • @BeHappyAndNice
    @BeHappyAndNice Год назад +1

    I love your channel, it is extremely useful. I have a question.
    How it is possible to persist an event by ef core change tracking that was raised in the rich model while the snapshot pattern is used to map the rich model to a model that is supposed to be persisted into the database?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      EF is tracking the "snapshot" model? And you're only using the rich model to execute your business logic?
      I'd build some IOutboxService that would just take the rich model, and create the require domain events.
      Or you can figure out a way to do it while mapping back to the snapshot model.

    • @BeHappyAndNice
      @BeHappyAndNice Год назад

      @@MilanJovanovicTech Thank you for your response.
      Yes I am using only my rich model to track the respective business logic and when I want to store any result to the database, I map the rich model to a snapshot model. So, any events that were raised inside of rich model, will be missed by ef core change tracker.

  • @Sara-po1jd
    @Sara-po1jd 8 месяцев назад

    thank you for a nice video, I have a question regarding using the MediatR in the domain layer. i kknow that that domain layer should not have any integration with other libraries, can you please explain why in your case you use an external library ? I would appreciate your answer.

  • @ramytawfik9168
    @ramytawfik9168 Год назад +1

    Another question please what do you mean by 'Atomic' in the latest approach, Do you mean that we will either persist the business logic and the event in the db or if there is any problem then we will rollback the business logic and also the event ?

  • @z0n_
    @z0n_ Год назад +2

    I am not really a fan of publishing integration-events inside domain-event handlers. I think it's better to have a clear separation between the domain- and integration-events. Domain-events are handled as a part of the transactions and integration-events are published after the transaction has completed.
    It still does not fix the problem where publishing the integration-events fails but you could always switch to using outbox pattern.
    How about this?
    // Application layer
    class DomainEventHandler
    {
    public DomainEventHandler(DbContext dbContext) { ... }
    public Handle(SomeDomainEvent event)
    {
    var someEntity = this._dbContext.GetSomeEntityBy(event.Data);
    someEntity.Update(event.Data2);
    someEntity.RaiseIntegrationEvent(new SomeIntegrationEvent());
    }
    }
    And inside SaveChanges()
    publishDomainEvents();
    base.SaveChanges();
    publishIntegrationEvents();
    Domain-events are published inside domain layer and integration-events are published in the application layer. Domain-events handlers can be a part of the transaction and integration-events are published after the transaction has completed.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      I'd rather separate integration events from the main business transaction using an Outbox, it leads to a more robust implementation

  • @LucasHenriquedeBrito
    @LucasHenriquedeBrito 11 месяцев назад +1

    Question. I have a CreateSomethingAHandler and during this handler, my domain has raised an event. So I will have AEventHandler. During AEventHandler, can this AEvent raise another Event? like a chair event? Does it sound like bad practice? CreateHandler -> Domain raise an event-> EventHandler-> Domain can Raise another EventHandler?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      In general - it's not a bad practice. But I would definitely consider using an Outbox. Chaining so many domain events can lead to a pretty large transaction.

  • @adriano.digiere
    @adriano.digiere Год назад +1

    Hi Milan! I have one question.
    When we are removing a line item, this is done by a function inside the aggregate root Order. So we can call the function Raise passing the LineItemRemovedDomainEvent.
    How would be the approach to an aggregate root deletion (ex: Order)? We would have to expose the Raise function and call it from the handler?
    Thanks.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      Or create a method on the Aggregate root called "Cancel"/"Remove"?

    • @adriano.digiere
      @adriano.digiere Год назад

      ​@@MilanJovanovicTech This method would be responsible just for raising the event? What would prevent a programmer from deleting the aggregate root without calling this method?
      Thanks for the answer.

  • @dragannikolic568
    @dragannikolic568 Год назад +1

    Hi Milan, Thx again for nice introduction to domain events!
    1. Is implementation of the Application's OrderCreatedEvent.cs:
    internal record OrderCreatedEvent(Guid Id); or we need something more?
    2. May I ask for the name the VS theme that you're using. Very simple and nice one.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      1) Yes
      2) I'm using native VS dark theme + ReSharper syntax highlighting

    • @dragannikolic568
      @dragannikolic568 Год назад

      @@MilanJovanovicTech Thx for answering!!! I'm using VS17.5.5 default dark theme but am not using Resharper. Difference might be there. I have to install some version of Resharper although VS has a lot of builtin features regarding helping in coding already. Thx. again!

  • @adiviuh3693
    @adiviuh3693 Год назад +1

    Hi, Milan. I want to ask you to create a video about Cancellation token. I know what is it, but I'm interesting in situation there I have to implement the cancellation callback for production. This thing possibly the most frequently used element and a lot of developers actually don't understand how to use it. (As am I actually😅).
    I'm coming to read.

  • @volodymyrliashenko1024
    @volodymyrliashenko1024 Год назад +1

    So..... Everything is possible to implement without MediatR.
    And it will have exactly the same behavior but without additional framework.
    Please correct me if I'm wrong.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      I'm only using MediatR to publish events and trigger the handlers. You can easily solve that without MediatR if you want to

  • @rohit704
    @rohit704 Год назад +1

    Milan, can we store saga in MS-SQL apart from StoreInPostgres?

  • @tiagosantos2136
    @tiagosantos2136 4 месяца назад

    Why is domain event publishing being implemented in ApplicationDbContext? Shouldn't this be implemented in UnitOfWork (of course, if you are using the pattern)?

  • @user-cp8hr2zr5k
    @user-cp8hr2zr5k 24 дня назад

    Hello, how can i publish domain events if i have separate domain and database models?

  • @arquimedesgarcia2632
    @arquimedesgarcia2632 7 месяцев назад +1

    Is the code available to download and practice?

  • @EHBRod13
    @EHBRod13 7 месяцев назад

    I use id value objects for my domain entities. So I have something like public sealed class domainEntityName : Entity { ... }. My domainEntityNameId inherits from public sealed class UserId : EntityId { ... }. At min 10:41, where you grab the domain events from the changetracker, would I put something like ChangeTracker.Entries() ? The reason I ask is because when I try to obtain my domain events, I get zero count.

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 месяцев назад +1

      You'd be better off creating an IEntity interface, with the methods to get and clear domain events
      ChangeTracker.Entries

    • @EHBRod13
      @EHBRod13 7 месяцев назад

      @@MilanJovanovicTech Oh, that’s a great idea! Thanks! Your vids have helped me so much

  • @jeremyhb1393
    @jeremyhb1393 Год назад +2

    Hii 🖐 I watched your video on creating domain events, and I found it very informative. However, I noticed that your implementation seems to violate the principle that the domain should not depend on any dependencies.

  • @ronaldschutte7948
    @ronaldschutte7948 6 месяцев назад

    Why not only trigger the event when a save was succesfull? Then you would only communicate the persistant state.

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 месяцев назад

      It's not atomic

    • @ronaldschutte7948
      @ronaldschutte7948 6 месяцев назад

      @@MilanJovanovicTech I understand. I kind of thought about this like strong vs eventual consistancy. When you only communicate what was saved, then you are sure that what you communicate is the same as the persistant state.

  • @husseinhajmohammed3812
    @husseinhajmohammed3812 Год назад +1

    what if i have domain events that change state of entities
    how this changes will save in database ?
    i think can solve this :
    await base.SaveChngesAsync();
    // publish events
    await base.SaveChangesAsync();

  • @haroldpepete
    @haroldpepete Год назад +1

    like Homer would say, yesssss but nottt, it didn't like what i saw, why do you use context database and you don't create a repository o service to use data layer, you have datacontext on each handler, ummmm it looks bad

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      You can extrapolate your own implementation from the example, that's good enough for me