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.
@CodeOpinion2 жыл бұрын
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
@yuryschkatula90263 жыл бұрын
6:00 Lines #31 and #36 just make me cry. And #33 and #38 make me smile ^^)
@thatoneuser86003 жыл бұрын
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.
@vadimprudnikov90723 жыл бұрын
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.
@Greenthum63 жыл бұрын
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.
@CodeOpinion3 жыл бұрын
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.
@mehdihadeli3 жыл бұрын
Hi, Thanks for this video, What is the advantage of usage of factory method instead of direct use of the constructor?
@CodeOpinion3 жыл бұрын
Private constructor that should be valid. Provide a factory that uses it.
@mehdihadeli3 жыл бұрын
@@CodeOpinion Do we force to use factory here? Could we handle it inner a public constructor?
@stefanoproiu23763 жыл бұрын
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?
@CodeOpinion3 жыл бұрын
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.
@FlaviusAspra3 жыл бұрын
@@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.
@HackensackSockoKicky3 жыл бұрын
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?
@johnbryan10493 жыл бұрын
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.
@HackensackSockoKicky3 жыл бұрын
@@johnbryan1049 why can’t you enforce the constraints in the constructor and throw if they’re not met?
@CodeOpinion3 жыл бұрын
I prefer not to throw in the constructor.
@danflemming35533 жыл бұрын
@@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.57623 жыл бұрын
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 :)
@CodeOpinion3 жыл бұрын
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!
@kinggrizzly133 жыл бұрын
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.
@joaomelo66423 жыл бұрын
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?
@CodeOpinion3 жыл бұрын
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.
@ranulpallemulle54473 жыл бұрын
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!
@CodeOpinion3 жыл бұрын
Check out this video that I did on that exact topic/question: kzbin.info/www/bejne/faW6h3qApZVpZ6M
@richardhaughton96333 жыл бұрын
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
@Pretence013 жыл бұрын
@@richardhaughton9633 a private empty constructor is enough for EFCore
@evaldasraisutis30583 жыл бұрын
Would love to see how you would load such an aggregate from the database, detect changes and persist them back to the database.
@CodeOpinion3 жыл бұрын
Check out this video I did on persistence. kzbin.info/www/bejne/faW6h3qApZVpZ6M
@dariogriffo3 жыл бұрын
There is a test on the repo called aggregate tests, that's how you can load an aggregate, make changes and persist
@fabiotlessa2 жыл бұрын
Thanks for the video. How would be your suggestion for the factory method to build objects with inheritance.
@CodeOpinion2 жыл бұрын
Factory methods, often just private statics on the class itself which calls a private constructor.
@tulliandar3 жыл бұрын
I have never heard “giraffe mode” like this. I understand what you’re saying, but can you explain why you call it that, please?
@Cypressious3 жыл бұрын
I think he was saying "draft mode".
@tulliandar3 жыл бұрын
@@Cypressious that makes much more sense! Thanks
@CodeOpinion3 жыл бұрын
Sometimes I talk quick and things muddy. Most often it occurs when using acronyms.
@flavioneto10813 ай бұрын
this made me lmfao for some reason, thanks
@rodrigolira833 жыл бұрын
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!
@CodeOpinion3 жыл бұрын
Yes, test the factory. If you really want to go far, check that there's no public ctor.
@jonaslomholdt3 жыл бұрын
Yes! This is the way!
@CodeOpinion3 жыл бұрын
It sure helps!
@michaelgray64383 жыл бұрын
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