ALWAYS Valid Domain Model

  Рет қаралды 11,200

CodeOpinion

CodeOpinion

Күн бұрын

Пікірлер
@haraheiquedossantos4283
@haraheiquedossantos4283 2 жыл бұрын
What do you do when you want to validate properties consistency of your domain model? Like if a field is required, numeric field must be greater than zero and so on. Do you make those validation inside the domain model or make them inside the command messages using some library like FluentValidation or DataAnnotation? Or make validation on both of them? I'm asking this because I saw different people in area doing these three different approaches, and I'd like to know your opinion about.
@CodeOpinion
@CodeOpinion 2 жыл бұрын
I'd consider most of that pretty trivial validation. I'd prefer to use value objects or another types to enforce that type of validation. Check out kzbin.info/www/bejne/b5TVaJqog7yhbMU
@yuryschkatula9026
@yuryschkatula9026 3 жыл бұрын
6:00 Lines #31 and #36 just make me cry. And #33 and #38 make me smile ^^)
@thatoneuser8600
@thatoneuser8600 3 жыл бұрын
Notes - How to make your domain model always valid: 1. Give commands guard clauses that check against invariants that exist in your Bounded Context, throwing an exception if they're not met 2. Replace constructor with Factory Method in the root that also has guard clauses for invariants that throw exceptions if not met (so that invalid arguments can't be received from other classes) 3. In a different root that needs to create the root of #2, create a simple delegate query method that calls and returns the value of its factory method. It doesn't need to have guard clauses, since the factory method checks itself if it's valid.
@vadimprudnikov9072
@vadimprudnikov9072 3 жыл бұрын
Thanks for the video! I would implement the factory a bit differently :) I prefer when a component doesn't allow doing bad things at compile time rather than at runtime. I would probably create a Stops class with builder-like methods, and that class will rearrange stops in a particular order. Then, the Stops instance can be passed to the aggregate's constructor. It's kind of getting the valid state by nature apposed to watching what the caller code is doing and throwing exceptions.
@Greenthum6
@Greenthum6 3 жыл бұрын
It is so great to learn DDD while working daily with old enterprise transactional mess: Validations and checks everywhere written differently every time, random transactional issues here and there... It is not fair to compare simple domain model example with an old huge system in production, but most of us know where it goes and how it ends.
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Yes, those of us who dealt or are dealing with what you described see the value in a model that is a consistency boundary that is always in a valid state.
@mehdihadeli
@mehdihadeli 3 жыл бұрын
Hi, Thanks for this video, What is the advantage of usage of factory method instead of direct use of the constructor?
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Private constructor that should be valid. Provide a factory that uses it.
@mehdihadeli
@mehdihadeli 3 жыл бұрын
@@CodeOpinion Do we force to use factory here? Could we handle it inner a public constructor?
@stefanoproiu2376
@stefanoproiu2376 3 жыл бұрын
In the Arrive() method of the Stop class you are returning void. This makes sense: If everything goes right, the method executes successfully. If there's something wrong, the method throws an exception. The client of the method has to wrap the call in a try-catch block in order to handle a possible failure, but as the method evolves in time, it might throw different exceptions that clients are not forced to handle because all exceptions are unchecked in C#. What do you think about being explicit on the result of an operation (in a functional style) and return some information either about how the state of the object changed (maybe an event) or about what caused the failure (modeled as a separate class for each concrete type of failure), all wrapped in a OneOf type, then let the client handle the result with pattern matching?
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Ya for sure, I got nothing against using OneOf or a Maybe to give back the client rather than throwing. I actually prefer that in many situations.
@FlaviusAspra
@FlaviusAspra 3 жыл бұрын
@@CodeOpinion Strictly speaking, the union of all exceptions being thrown by a method belong to the return type specification of that method. Having there "void" is a lie, but I think here most OOP language implementators got OOP wrong. Think Liskov.
@HackensackSockoKicky
@HackensackSockoKicky 3 жыл бұрын
Maybe I missed it in the video, but what is the reason for static factory methods instead of using constructors? Wouldn’t that achieve the same?
@johnbryan1049
@johnbryan1049 3 жыл бұрын
Using a static factory method forces the consumer of your class to construct it in a valid state as you (the author) can force any necessary constraints. If you use a constructor, the user of your class can pass in any values they want (valid or otherwise). It's simply a way of enforcing validity.
@HackensackSockoKicky
@HackensackSockoKicky 3 жыл бұрын
@@johnbryan1049 why can’t you enforce the constraints in the constructor and throw if they’re not met?
@CodeOpinion
@CodeOpinion 3 жыл бұрын
I prefer not to throw in the constructor.
@danflemming3553
@danflemming3553 3 жыл бұрын
@@CodeOpinion Why do you prefer not to throw exceptions in the c-tor? What problems do you see with that? Factory method make sense in some cases, but I can't see how it helps in the example of ShipAggregateRoot class ('Factory' is not actually a verb, but that's a different topic). Thanks!
@olegasg.5762
@olegasg.5762 3 жыл бұрын
Good video, thanks! This is what I am trying to do in the current project. But I would avoid putting "AggregateRoot" in the class name as it hurts for readability. If you want to mark an entity that it is an aggregate root then it's better to create an empty interface IAggregateRoot and make that entity "implement" it. Just my advice :)
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Agree, I generally don't suffix names this way, it was more for clarity in the example but I think I need to avoid it going forward so folks don't assume to actually many things this way. Thanks for the comment!
@kinggrizzly13
@kinggrizzly13 3 жыл бұрын
I was thinking the same thing, but then I read how marker interfaces are frowned upon. But I still like the market interface implementation regardless of opinions on stackover flow.
@joaomelo6642
@joaomelo6642 3 жыл бұрын
another great content. is nice to find content as yours in the middle of so many tutorials. ever consider mix other languages in the examples like typescript or python?
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Yes I have thought about it because I get so many more comments like this where people are not necessarily using C# but can still get the overall gist of the topic. I'll be thinking more about it for future videos. Thanks for the feedback.
@ranulpallemulle5447
@ranulpallemulle5447 3 жыл бұрын
Thanks! Would you say this is essentially about favoring a rich domain model rather than an anemic one? An issue I've had with aggregates that validate everything is when it comes to persistence with an ORM (EF Core to be exact). Maybe I am just mixing concerns here, but I've found it difficult to map my persistence layer objects to my domain aggregates without some framework dependent modifications to the model such as introducing private setters when really all i need is a getter, and keeping a default constructor around for EF core to use even though I'd like to ideally have a single constructor that makes sure everything is valid at the time of creation. Would be great if you have some pointers!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Check out this video that I did on that exact topic/question: kzbin.info/www/bejne/faW6h3qApZVpZ6M
@richardhaughton9633
@richardhaughton9633 3 жыл бұрын
Excellent question. I have the same problem. My aggregate need a parameterless constructor for EF to work giving me a hard time to enforce a valid state on creation. Maybe C#9 records can help us but I hate them when dealing with non-trivial objects
@Pretence01
@Pretence01 3 жыл бұрын
@@richardhaughton9633 a private empty constructor is enough for EFCore
@evaldasraisutis3058
@evaldasraisutis3058 3 жыл бұрын
Would love to see how you would load such an aggregate from the database, detect changes and persist them back to the database.
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Check out this video I did on persistence. kzbin.info/www/bejne/faW6h3qApZVpZ6M
@dariogriffo
@dariogriffo 3 жыл бұрын
There is a test on the repo called aggregate tests, that's how you can load an aggregate, make changes and persist
@fabiotlessa
@fabiotlessa 2 жыл бұрын
Thanks for the video. How would be your suggestion for the factory method to build objects with inheritance.
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Factory methods, often just private statics on the class itself which calls a private constructor.
@tulliandar
@tulliandar 3 жыл бұрын
I have never heard “giraffe mode” like this. I understand what you’re saying, but can you explain why you call it that, please?
@Cypressious
@Cypressious 3 жыл бұрын
I think he was saying "draft mode".
@tulliandar
@tulliandar 3 жыл бұрын
@@Cypressious that makes much more sense! Thanks
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Sometimes I talk quick and things muddy. Most often it occurs when using acronyms.
@flavioneto1081
@flavioneto1081 3 ай бұрын
this made me lmfao for some reason, thanks
@rodrigolira83
@rodrigolira83 3 жыл бұрын
Hi! You mentioned that you don't have to question having two stops as you're working with always valid aggregates. But do you write tests for that? I mean, to make sure a future refactoring wouldn't break this rule? Thanks!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Yes, test the factory. If you really want to go far, check that there's no public ctor.
@jonaslomholdt
@jonaslomholdt 3 жыл бұрын
Yes! This is the way!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
It sure helps!
@michaelgray6438
@michaelgray6438 3 жыл бұрын
I’m a big fan of the factory methods to create the aggregates, allows you to speak the language and make it clear what state an aggregate is getting created in. Great vid again
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Thanks comment and for watching!
Leaking Value Objects from your Domain
6:57
CodeOpinion
Рет қаралды 16 М.
Domain Modeling Gone Wrong - Part 1
8:21
CodeOpinion
Рет қаралды 29 М.
Try this prank with your friends 😂 @karina-kola
00:18
Andrey Grechka
Рет қаралды 9 МЛН
小丑女COCO的审判。#天使 #小丑 #超人不会飞
00:53
超人不会飞
Рет қаралды 16 МЛН
IL'HAN - Qalqam | Official Music Video
03:17
Ilhan Ihsanov
Рет қаралды 700 М.
Kill Anemic Domain Models with Encapsulation: The Hard Part
15:04
Zoran Horvat
Рет қаралды 10 М.
What is a Domain Service in Domain-Driven Design?
12:49
Milan Jovanović
Рет қаралды 23 М.
5 Mistakes That Make Your Code Unmaintainable
13:47
CodeOpinion
Рет қаралды 7 М.
Don’t Let Your Domain Model Depend on Current Time!
10:03
Zoran Horvat
Рет қаралды 6 М.
This Is How the Anemic Domain Model Turns Bad
13:08
Zoran Horvat
Рет қаралды 10 М.
Modeling a Domain With Domain-Driven Design From Scratch | DDD
19:10
Milan Jovanović
Рет қаралды 97 М.
Try this prank with your friends 😂 @karina-kola
00:18
Andrey Grechka
Рет қаралды 9 МЛН