Is an Anemic Domain Model an Anti-Pattern?

  Рет қаралды 21,913

Milan Jovanović

Milan Jovanović

Күн бұрын

Пікірлер: 100
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@datka89
@datka89 10 ай бұрын
Are there Authentication and Authorization in your lessons using Clean Architecture, Milan?
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
@@datka89 You mean course? 🤔
@MahmoudIsmail-rw7hg
@MahmoudIsmail-rw7hg Жыл бұрын
I like that you make example from scratch, you show the problem and then the solution
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
The correct way to learn, IMO
@nove1398
@nove1398 Жыл бұрын
+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 Жыл бұрын
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
@sotsch9280
@sotsch9280 Жыл бұрын
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 Жыл бұрын
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
@alexlo5655
@alexlo5655 Жыл бұрын
Thank you for the video. Waiting for the video where you will explain how to work with rich model Order and database.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That'll be coming out next week 😁
@kodindoyannick5328
@kodindoyannick5328 7 ай бұрын
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!
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Awesome, glad it's helpful :)
@m5s10
@m5s10 Жыл бұрын
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 😁
@anilkarasahh
@anilkarasahh Жыл бұрын
I love your videos so much! You go from zero to hero in every one of your videos.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Wow, thank you!
@justtomi-qp8qj
@justtomi-qp8qj Жыл бұрын
Nice and structured explanation! Big applause for mentioning pros of having anemic domain model and cases. Well done!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Much appreciated!
@Pest87
@Pest87 Жыл бұрын
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.
@dcuccia
@dcuccia Жыл бұрын
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.
@klausp.893
@klausp.893 11 ай бұрын
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 11 ай бұрын
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
@hkoueke
@hkoueke Жыл бұрын
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. 😁
@10199able
@10199able Жыл бұрын
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 Жыл бұрын
@@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!
@vatmanzlokuz680
@vatmanzlokuz680 3 ай бұрын
your videos are awesome, i am learning very much with each video, each pattern wath you teach and show is very usefull
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Happy to hear that!
@pedroxillovich8622
@pedroxillovich8622 Жыл бұрын
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.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
With EF Core that's relatively easy to do
@izzychen7537
@izzychen7537 Жыл бұрын
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.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I wasn't aware it had a name 😁
@ВиталийБулдаков-ш4э
@ВиталийБулдаков-ш4э Жыл бұрын
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.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I have quite a few EF Core videos already
@kasozivincent8685
@kasozivincent8685 Жыл бұрын
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
@deefstes
@deefstes 11 ай бұрын
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.
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
I appreciate the feedback very much!
@cyril113
@cyril113 Жыл бұрын
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.
@vasiliioleinic
@vasiliioleinic Жыл бұрын
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 Жыл бұрын
I don't think it's unpopular opinion, rather just a different approach to implementing a solution. Both get the job done :)
@volodymyrliashenko1024
@volodymyrliashenko1024 Жыл бұрын
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?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I'll show that in a future video :)
@clem_grim
@clem_grim Жыл бұрын
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?
@mahmoudalaskalany
@mahmoudalaskalany Жыл бұрын
Great one as usual milan 🔥
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thank you!
@CoachOL
@CoachOL Жыл бұрын
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 4 ай бұрын
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 28 күн бұрын
1) Get rid of nulls everywhere 2) Check if something is null before accessing it
@ramytawfik9168
@ramytawfik9168 Жыл бұрын
Thanks for your great effort
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Don't mention it
@microtech2448
@microtech2448 Жыл бұрын
Nicely explained
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks a lot!
@DaminGamerMC
@DaminGamerMC Жыл бұрын
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
@RonyCuzco
@RonyCuzco Жыл бұрын
great content! thanks for sharing!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Glad you enjoyed it!
@ryoman76
@ryoman76 Жыл бұрын
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
@yeganehaym
@yeganehaym Күн бұрын
What about create method have more parameters and we want use mapster to map dto to model? How is that?
@MilanJovanovicTech
@MilanJovanovicTech Күн бұрын
That's fine
@canalDoRanyOficial
@canalDoRanyOficial Жыл бұрын
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 Жыл бұрын
Don't use DDD entities for that query, just return a response model
@canalDoRanyOficial
@canalDoRanyOficial Жыл бұрын
@@MilanJovanovicTech thank you!
@KashmirThakur-goldi
@KashmirThakur-goldi Жыл бұрын
Good explanation 👍
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks 🙂
@kimfom
@kimfom 4 ай бұрын
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 4 ай бұрын
I meant more like - creating the Order from different flows: - Normal flow (checkout) - Copying an existing order - Wishlist/waitlist into order
@kimfom
@kimfom 4 ай бұрын
@@MilanJovanovicTech yeah makes sense now thanks for clarifying
@edwardchovaklinov180
@edwardchovaklinov180 3 ай бұрын
Do we need to have a static method in the rich domain model for creation?
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
No, there's also the constructor. But I don't like having side effects in constructor (like raising domain events).
@aj.arunkumar
@aj.arunkumar 4 ай бұрын
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 4 ай бұрын
Yes, EF Core can use private ctors and setters
@aj.arunkumar
@aj.arunkumar 4 ай бұрын
@@MilanJovanovicTech thanks for the reply
@nayanchoudhary4353
@nayanchoudhary4353 Жыл бұрын
This is good! 🙂
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thank you :)
@ahmedameen2
@ahmedameen2 29 күн бұрын
Simple answer, with anemic model you can't control the object state from one place
@MilanJovanovicTech
@MilanJovanovicTech 29 күн бұрын
Well, you can if all the methods modifying it are in one place
@HenrryPires
@HenrryPires 4 ай бұрын
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 4 ай бұрын
That's the debate between a transaction script and a domain model
Mapping Domain-Driven Design Concepts To The Database With EF Core
18:06
Milan Jovanović
Рет қаралды 51 М.
Is an ANEMIC Domain Model really that BAD?
10:36
CodeOpinion
Рет қаралды 18 М.
The Joker wanted to stand at the front, but unexpectedly was beaten up by Officer Rabbit
00:12
Brawl Stars Edit😈📕
00:15
Kan Andrey
Рет қаралды 52 МЛН
Please Help This Superhero! 🙏
00:48
Alan Chikin Chow
Рет қаралды 8 МЛН
How to design great Aggregate Roots in Domain-Driven Design
11:30
Milan Jovanović
Рет қаралды 13 М.
Kill Anemic Domain Models with Encapsulation: The Hard Part
15:04
LINQ's INSANE Improvements in .NET 9
11:26
Nick Chapsas
Рет қаралды 37 М.
Денис Цветцих - Rich Model и Anemic Model: враги или друзья
52:59
DotNext — конференция для .NET‑разработчиков
Рет қаралды 2,6 М.
How Strongly Typed IDs Can Make Your Code More Expressive | DDD
12:02
Milan Jovanović
Рет қаралды 33 М.
What is a Domain Service in Domain-Driven Design?
12:49
Milan Jovanović
Рет қаралды 20 М.
Domain Models: Anemic vs Rich
20:03
Sergei Calabonga
Рет қаралды 2,2 М.
Avoid This Common Mistake in DDD Modeling
10:17
Zoran Horvat
Рет қаралды 9 М.
Владимир Хориков - Domain-driven design: Cамое важное
1:13:59
DotNext — конференция для .NET‑разработчиков
Рет қаралды 54 М.