Is an Anemic Domain Model an Anti-Pattern?

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

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

  • @MilanJovanovicTech
    @MilanJovanovicTech  ปีที่แล้ว +7

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

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

      Are there Authentication and Authorization in your lessons using Clean Architecture, Milan?

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

      @@datka89 You mean course? 🤔

  • @nove1398
    @nove1398 ปีที่แล้ว +13

    +1 for explanation from scratch. +1 for explaining a common case where a domain does not really need to be rich for productivity. +1 for detailed examples. Great video, looking out for more content as usual!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      I'll try to keep it like this in the future videos, but for some topics I really can't start from scratch 😁

    • @nove1398
      @nove1398 ปีที่แล้ว

      @@MilanJovanovicTech totally understand, appreciate it

  • @MahmoudIsmail-rw7hg
    @MahmoudIsmail-rw7hg ปีที่แล้ว +4

    I like that you make example from scratch, you show the problem and then the solution

  • @sotsch9280
    @sotsch9280 ปีที่แล้ว +7

    Good explanation! One Point to mention is that you dont need all those factory methods. Just use standard public ctor! This makes It more clear what a new instance requires to be created when using new keyword.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +2

      One reason I prefer factory methods is ORMs - they'll call the ctor when materializing objects from the database.
      And I can add side-effects with factory methods which don't really fit inside a ctor.

    • @sotsch9280
      @sotsch9280 ปีที่แล้ว

      @@MilanJovanovicTech this is right! But then you have kind of a persistence aware domain, so its a design decision. Another solution is to add a private ctor when orm needs to intantiate an object, which is also persistence aware (but this time with 'new-keyword flavor'). What do you mean with side-effects? If you want to have different creation behaviours? Also fit into ctor

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

    I have a good base with this video which allows me to follow other of your videos or see again those already seen. I learn new good things from you every time. Thank you so much!

  • @m5s10
    @m5s10 ปีที่แล้ว +2

    I just noticed you're almost at 50k subscribers. Well done man, keep it up :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Getting there! A few more days and we should get 50k. Gotta start planning some surprise 😁

  • @alexlo5655
    @alexlo5655 ปีที่แล้ว +6

    Thank you for the video. Waiting for the video where you will explain how to work with rich model Order and database.

  • @justtomi-qp8qj
    @justtomi-qp8qj ปีที่แล้ว +1

    Nice and structured explanation! Big applause for mentioning pros of having anemic domain model and cases. Well done!

  • @anilkarasahh
    @anilkarasahh ปีที่แล้ว +2

    I love your videos so much! You go from zero to hero in every one of your videos.

  • @hkoueke
    @hkoueke ปีที่แล้ว +1

    Watching you from Cameroon. Great content. I learn a lot from your videos.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Much love for Africa. I'm happy you're finding the videos insightful. 😁

  • @dcuccia
    @dcuccia ปีที่แล้ว +2

    Great post. One additional thing to consider is that data validator functions often live "somewhere else" than the data, especially in cloud scenarios. A functional approach to this problem might be to have a domain model that imagines both an Order entity, and a ValidatedOrder entity. And then, any functionality that relies on an order being validated can take an explicit dependency on ValidatedOrder (produced by an OrderValidator, of course!). "init" and "required" properties can help with baseline completeness, in the meantime. I'd still consider this a rich domain model, but the richness is pushed to the functions/actions, not the data.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      That's quite a peculiar approach. Do you have any resources about that?

    • @dcuccia
      @dcuccia ปีที่แล้ว

      @@MilanJovanovicTech Scott Wlaschin's "Domain Modeling Made Functional" book and lectures would be a start.

    • @dcuccia
      @dcuccia ปีที่แล้ว

      See, e.g. EmailValidationService discussion in his 2019 KanDDDinsky talk on YT.

  • @Pest87
    @Pest87 ปีที่แล้ว +1

    This DDD series is the best explanation for DDD I've ever seen online.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I'm glad you think so, because I spent countless hours studying DDD 😅
      I'll be releasing an in-depth course next month about Clean Architecture and DDD, where I'll do a much better job of explaining everything.

    • @Pest87
      @Pest87 ปีที่แล้ว

      @@MilanJovanovicTech Thank you, good to know that. Indeed DDD is a very debatable topic. I see more and more developers not favouring it, but I also see very bad implementations of it which I think leads to the first one.

  • @klausp.893
    @klausp.893 ปีที่แล้ว +2

    Thanks for the video. It looks very nice at first sight.
    However, it gets complicated when you look at a real application. For a line item you might need 12 parameters or more. You don't want to pass those as parameters, so you need another DTO class, which of course again contains public set or init. You also need to be able to change the line items afterwards. So for every little thing a separate function - SetQuantity(), AddDiscount() etc. . This turns a "rich domain model" quickly into a "fat domain model".

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      If you focus on "behavior" it starts making sense - regardless of the number of properties. You don't need a SetX method for each property

  • @pedroxillovich8622
    @pedroxillovich8622 ปีที่แล้ว +2

    Very good examples, about antipattern or patterns , we have a lot and allways depends of the context I prefer to consider as a different way and not as an anti pattern. Also remember that for few ORMs you need to do some configurations to save private properties in the db. For example if you want to save a complex object with private properties in cosmos db.

  • @mahmoudalaskalany
    @mahmoudalaskalany ปีที่แล้ว +1

    Great one as usual milan 🔥

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

    your videos are awesome, i am learning very much with each video, each pattern wath you teach and show is very usefull

  • @deefstes
    @deefstes ปีที่แล้ว +1

    Great concise explanation of what the Anemic Domain Model is, but the video didn't really discuss the question posed in the title "Is an Anemic Domain Model an Anti-Pattern?" I get what the disadvantages of the ADM is and how the RDM addresses those. And I think we all know that the ADM is commonly considered an anti-pattern. Or at least, that's how Martin Fowler described it when he coined the term. But I was hoping this video would delve into that discussion a bit more and maybe suggest why it might not be considered an anti-pattern. Otherwise a title of "What is the Anemic Domain Model" would perhaps have been more accurate.
    Great content nevertheless. Milan is my goto channel for .NET related topics, hands down.

  • @cyril113
    @cyril113 ปีที่แล้ว +2

    You can extract the business logic of order creation into it's own component that doesn't have state. You can do the same without mixing state and logic. Basically like in a functional programming languages. In realistic scenarios your domain model code will have external dependencies like EF or some external services. It could get ugly when you have to supply those dependencies to your domain model. Well I guess thats DDD.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Of course, it's possible to use a domain service to extract that logic. There's no need to introduce external dependencies to domain models though.

  • @kasozivincent8685
    @kasozivincent8685 ปีที่แล้ว +1

    I appreciate your efforts to make DDD approachable, most books do more talking than showing code.
    I have some questions though. Is it really good to use record types for value objects? I have found them so lacking.
    1. We simply can’t use their awesome primary constructor. Why? It breaks domain invariants. There is validation. In most cases we prefer the smart constructor pattern.
    2. They don’t implement IComparable out of the box. Say I want to return products that code less than a given price? Money has to implement IComparable for that to work.
    3. Their comparison semantics are lacking especially when the value object contains some sort of collection. Some times we don’t want to use all the values for comparison.
    I came across a lib that provides a full fledged ValueObject class that provides all this plumberinf for free.
    What are your thoughts on this?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I've switched to using records and I'm not looking back. The drawbacks are negligible most of the time.
      The problem with collection is they are reference types, not in the record itself.

    • @kasozivincent8685
      @kasozivincent8685 ปีที่แล้ว

      @@MilanJovanovicTech Yeah I agree with you on this. Most code bases can live happily with value objects as records.
      I didn’t say that the problem is with the record, I said if it contains a reference type (collection) then we need something else.
      Thanks

  • @izzychen7537
    @izzychen7537 ปีที่แล้ว +1

    Good video, just one comment- Properties/Collections being accessed directly is indeed an anti-pattern to the point where it has a name- Law of Demeter.

  • @microtech2448
    @microtech2448 ปีที่แล้ว +1

    Nicely explained

  • @RonyCuzco
    @RonyCuzco ปีที่แล้ว +1

    great content! thanks for sharing!

  • @ВиталийБулдаков-ш4э
    @ВиталийБулдаков-ш4э ปีที่แล้ว +1

    Hi, Milan. Thanks for your great work. It would be nice if you make videos about ef core. Targeting more deep view on how it works. Like when it creates database connection etc.

  • @ramytawfik9168
    @ramytawfik9168 ปีที่แล้ว +1

    Thanks for your great effort

  • @vasiliioleinic
    @vasiliioleinic ปีที่แล้ว +4

    Thx for great explanation. However maybe unpopular opinion over here from practices you can achieve great things even with ’anemic models’ even in pretty big systems if your resource accessor layer has the well defined operations around atomic business verbs.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +4

      I don't think it's unpopular opinion, rather just a different approach to implementing a solution. Both get the job done :)

  • @KashmirThakur-goldi
    @KashmirThakur-goldi ปีที่แล้ว +1

    Good explanation 👍

  • @10199able
    @10199able ปีที่แล้ว +5

    How to work with rich model Order and database? There should be some anemic model in the middle?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      You can map it to the DB directly with an ORM like EF Core

    • @Ree1BigChris
      @Ree1BigChris ปีที่แล้ว

      @@MilanJovanovicTech yeah but how do you load an order from the database?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +8

      @@Ree1BigChris I'll show that in a future video, since I see it's causing confusion 😁

    • @georgepagotelis
      @georgepagotelis ปีที่แล้ว

      It’s confusing because we’ll have DTO for Ef core (mappers) n request/response (mappers) I assume you’re heading.

    • @matasbernotas3815
      @matasbernotas3815 ปีที่แล้ว

      @@MilanJovanovicTech That would be great. I'm always working with ADM and this approach would really improve my codebase. Would love to see full example with EF!

  • @clem_grim
    @clem_grim ปีที่แล้ว +2

    How to you instantiate this model when you load the data from the database if the constructor is private? You cannot really call "create()" as that's not a new entity

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      In this case EF Core will take care of it, otherwise you'd have to do it manually

    • @clem_grim
      @clem_grim ปีที่แล้ว

      @@MilanJovanovicTech by manually, you mean that the constructor should be public or that we should create another static method to instantiate a domain entity from a dataset?

  • @volodymyrliashenko1024
    @volodymyrliashenko1024 ปีที่แล้ว +1

    How to work with EF in this case?
    Are you going to have another entity class for the database?
    It would be nice to see the full workflow where you still have OrderService and you need to have a mapping between your Order class which encapsulates logic and your Order entity class.
    How would repository implementation look like?

  • @CoachOL
    @CoachOL ปีที่แล้ว +1

    Hi Milan, thank you very much for your content ! How do you deal with all the warnings Visual Studio shows when working with nullables?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Ignore them 🤣

    • @iliyan-kulishev
      @iliyan-kulishev 5 หลายเดือนก่อน

      The best is to make the code pass all of them. In my team we have configured our projects to treat these warnings as errors, so Visual Studio won't build if those are not resolved.

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

      1) Get rid of nulls everywhere
      2) Check if something is null before accessing it

  • @canalDoRanyOficial
    @canalDoRanyOficial ปีที่แล้ว +1

    Hi Milan! Greetings from Brazil!
    Could you make a video about the best way to use DDD (rich domain) with EF CORE? I have two screens that use different attributes but have one constructor.
    How can I implement the best select function? For example, for one screen, I need to select only the product ID: context.Product.select(product => product.Id). For another screen, I need to select only the product name: Context.product.select(product => product.Name).
    Do you recommend using two constructors in the same class?
    I apologize for my poor English.
    Your videos are great!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Don't use DDD entities for that query, just return a response model

    • @canalDoRanyOficial
      @canalDoRanyOficial ปีที่แล้ว

      @@MilanJovanovicTech thank you!

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

    Do we need to have a static method in the rich domain model for creation?

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

      No, there's also the constructor. But I don't like having side effects in constructor (like raising domain events).

  • @ryoman76
    @ryoman76 ปีที่แล้ว +1

    Hello Milan,
    great video.
    I don't understand how you use a rich model to make migrations?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      It works just fine, you'll see in Friday's video

    • @ryoman76
      @ryoman76 ปีที่แล้ว

      @@MilanJovanovicTech thank you so much, looking forward to it 👍I am really learning a lot from your videos

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

    At 4:18 you mentioned that there could be more than one places to create order. Why would one implement it that way isn't that what the OrderService is for? If you need to create an order you inject the order service and call the create method no? Where else or why would you implement the order create somewhere else? Maybe I'm too inexperienced to wrap my head around this. Please can you explain?

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

      I meant more like - creating the Order from different flows:
      - Normal flow (checkout)
      - Copying an existing order
      - Wishlist/waitlist into order

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

      @@MilanJovanovicTech yeah makes sense now thanks for clarifying

  • @aj.arunkumar
    @aj.arunkumar 6 หลายเดือนก่อน

    if we make the setters and constructors private, will we be able to use Entity framework? doesn't entity framework be able to create the domain instances when we are querying data from database?

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

      Yes, EF Core can use private ctors and setters

    • @aj.arunkumar
      @aj.arunkumar 6 หลายเดือนก่อน

      @@MilanJovanovicTech thanks for the reply

  • @nayanchoudhary4353
    @nayanchoudhary4353 ปีที่แล้ว +1

    This is good! 🙂

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

    What about create method have more parameters and we want use mapster to map dto to model? How is that?

  • @DaminGamerMC
    @DaminGamerMC ปีที่แล้ว +1

    Could you explain cancellation tokens? I see them everywhere and don't really understand what they do.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      They allow the client to cancel the request, and for the API to propagate that cancellation down the method chain

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

    Simple answer, with anemic model you can't control the object state from one place

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

      Well, you can if all the methods modifying it are in one place

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

    Haven’t you heard of use cases?

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

    I strongly desagree with your view. A POCO class like your orde class, should never contain logic, Single responsability Principle, leave the logic to a service. Make testing and abstraction so much easier and organized.
    Animic classes is somehting that i always enforce in my teams

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

      That's the debate between a transaction script and a domain model