How to design great Aggregate Roots in Domain-Driven Design

แชร์
ฝัง
  • เผยแพร่เมื่อ 6 ส.ค. 2024
  • ☄️ Master the Modular Monolith Architecture: bit.ly/3SXlzSt
    📌 Accelerate your Clean Architecture skills: bit.ly/3PupkOJ
    🚀 Support me on Patreon to access the source code: / milanjovanovic
    In this video, I'll do a deep dive into the theory behind Aggregates. I'm going to explain how to design an aggregate root and implement it in your .NET applications. The aggregate root pattern from Domain-Driven Design can help you create a better domain model. An aggregate acts as a consistency boundary and encapsulates one or more entities. Designing a good aggregate takes a lot of skill and practice.
    Join my weekly .NET newsletter:
    www.milanjovanovic.tech
    Read my Blog here:
    www.milanjovanovic.tech/blog
    Chapters
    0:00 What is an Aggregate?
    1:05 Why do we need Aggregates?
    2:15 What is an Aggregate (continued)
    5:42 Aggregate design best practices
    7:30 Let's look at an Aggregate example
  • วิทยาศาสตร์และเทคโนโลยี

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

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

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

  • @vantavoids
    @vantavoids 2 หลายเดือนก่อน +3

    honestly the fact that i was struggling all day with my aggregate roots and you happen to release a video talking about those specially... did you hide a mic under my desk??
    other than that top tier video as per usual please keep it up

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

      Glad it was helpful, and no worries I don't have a mic anywhere (or do I?)

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

    The value of your content is unique. Thanks Milan

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

    Great Milan, your explain a complex concept in a simple example! 👏

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

    awesome job milan, love you

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

    awesome

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

    Hi Milan. Nice video, appreciate it. Though not so good example on Workout aggregate, not showing any invariant between Workout and Exercises. Aggregate is about behavior and invariants and not about data.

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

      Wanted to focus on maintaining a consistency boundary

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

    Can you talk about Business Rule Engines and what are the design patterns appropriate to implement it?

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

    Would you happen to have more examples on the unit of work and how to save aggregate to database?

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

      Well, I've got a bunch of videos on the channel covering DDD aggregates directly or indirectly

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

    What do you mean by the use case?
    Thank you

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

      A component providing the desired functionality for one feature

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

    Hey Milan, what if you push your code examples to github so we can check the code while watching the video?

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

    Do you have this full course?

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

    Milan I implemented this full model and got update exceptions. I want to be able to add and delete within the aggregated tables but every add I do is recorded as a changestate modified not an insert. Is there some way to have it work correctly? I confirmed that if I use the dbContext and add directly to the entity object it is in a change state of Added. If I do not use the dbContext and add inside the aggregate root it is set to Modified.

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

      What is the "it" that's set to modified?

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

      @@MilanJovanovicTech the "it" is a child table. Example: Orders and OrderDetails. If I create an add method for OrderDetails in Orders aggregate root, as you have defined in your example, the add produces a change state Modified not Added. Throws a DbUpdateConcurrency exception because the row is not in the database yet. If Aggregate Root pattern does not intend to be used like this please let me know. In your example I'm doing exactly as you are adding an exercise to the workout aggregate root. If yours works and mine throws an exception I'm not sure why.

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

      I just did some deeper study on AggRoots. I get the feeling that AggRoot concept by definition requires that all records within the aggregate be created at the same time because of the interdependency that justifies the AR implementation. In the case of Order/OrderDetail it may be that it is NOT an AR model. Would like to get your opinion on that.

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

      Milan I have double checked the code. When you pushed down the Remove for exercise it deletes from the exercise collection within Workout domain object then you call SaveChanges(). The problem is the exercise collection is not tracked by EF. There is no insert getting written to the database for the Exercise added. This model of having an internal collection for the non-root aggregates is broken as I see it. There is no reference to the repository either, thus no way to cause the insert to occur. What is the right way to get an aggregate member inside the aggregate root to perform CRUD correctly?

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

      Ok, I have the answer to this issue in case it is helpful to anyone else. If the entity you add to the collection has an ID assigned it will treat it as an UPDATE and change state will be set by EF to Modified. I removed the ID and it accurately set the change state to Added. The problem here Milan is that the entity base classes are not allowing nullable ID's, which means you will ALWAYS get a Modified state and never a Added state. I don't know what this means to the base classes you have defined Milan. I would love to understand if there is a better way to successfully handle this. I had to set every property inside all entities to nullable in order to get the right behaviors. I do not think that is necessarily a good thing.

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

    The hidden gem inside this video could be the IReadOnlyList 🤔😎

  • @baranacikgoz
    @baranacikgoz 2 หลายเดือนก่อน +3

    The change you've done to the RemoveExercise method could not be left like that. You did not specified which Include's is used inside GetById method for Workout. If you decide to do that, it is wiser to conditionally include exercises of workouts by specifying exerciseId. Otherwise if there are millions of exercises you are loading all into memory just to remove one.

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

      If there are a large number of exercises, we would implement this differently... But we could also impose a business constraint that a workout can have at most 30 exercises.

    • @euler.chavez
      @euler.chavez 2 หลายเดือนก่อน +7

      @@MilanJovanovicTech What is this process like, or what would it be like? The "basic" examples are easy to understand, but the complex cases and their variations are rarely explained.
      For example, in a context where the Family is the aggregate, with entities such as Members and Addresses:
      a) If I need to obtain only the members, do I always have to access the aggregate?
      b) If I want to filter address based on type (house, work, business, etc), do I have to do it through the aggregate?

    • @ChristofferLund
      @ChristofferLund 2 หลายเดือนก่อน +8

      @@MilanJovanovicTech If you could provide an example of how you could elegantly solve this if the related entity has too many to load all into memory that would be nice. I find that to be one of the bigger challenges when using aggregates. Even just having a list of IDs could be too much at one point i presume

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

      @@ChristofferLund I'm curious how to solve this also. I think it will be a domain service.