Aggregate Design: Using Invariants as a Guide

  Рет қаралды 37,875

CodeOpinion

CodeOpinion

Күн бұрын

Пікірлер: 69
@skipodap1
@skipodap1 3 жыл бұрын
"Don't expose domain objects that can't enforce the business rules". That closing sentence was brilliant. Thanks for the vids
@CodeOpinion
@CodeOpinion 3 жыл бұрын
You're welcome
@RobLang
@RobLang 3 жыл бұрын
Been using DDD for over 10 years, popped in for a new take and although this confirmed what I knew, I just applaud and say it was explained brilliantly!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Thanks. Appreciate the comment.
@jacobmason6761
@jacobmason6761 3 жыл бұрын
I rarely ever comment on KZbin videos, but this is well deserved. You're concise and straight to the point, fantastic content. I struggled to find video resources on DDD and resorted to books, I wish this content was here when I first started learning. Please keep doing what you're doing!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
I really appreciate the comment. Thanks!
@xbmcme9768
@xbmcme9768 2 жыл бұрын
Really like the concrete examples. It's really hard to imagine a technical implementation of different concepts that I've never seen before in my life. Thanks for taking the time to make these videos. They are super helpful!
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Glad you liked it!
@secondry2
@secondry2 3 жыл бұрын
Since watching your videos my code quality has improved 10-fold and performs 10x better, not an exaggeration. Keep it up, loving the videos!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Glad they are helpful!
@kozer1986
@kozer1986 3 жыл бұрын
I'm crying of joy!!! Amazing channel. What I was looking for to grasp ddd more!
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Thanks! Hopefully the videos help.
@hesamkashefi
@hesamkashefi 3 жыл бұрын
Very good explanation. For me, the harder problem is how to find aggregate roots and their boundaries in a real-world project, it would be a very helpful video if you could make it for us.
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Find the invariants. Find out what the behaviors are and the data behind them. Map the actual workflow of the domain.
@ToeShimmel
@ToeShimmel 2 жыл бұрын
Your video's are fantastic. I keep coming back and they make me a much better developer. Thanks so much. You deserve more views!
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Much appreciated!
@NomadicBrian
@NomadicBrian 2 жыл бұрын
Excellent presentation. Walked away with a much clearer understanding of Aggregates.
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Glad it was helpful!
@victortodoran1828
@victortodoran1828 2 жыл бұрын
Ok, this one I had to watch three times, but I really enjoyed it in the end. This was a well picked example, the implementation is pretty nifty and smart and some good points were made. I did not care for what I supose is ddd lingo, but I gues that is on me to learn. Thanks for taking the time.
@CodeOpinion
@CodeOpinion 2 жыл бұрын
I try and avoid certain type of lingo but sometimes it's unavoidable or I do a poor job and assume it's common. Appreciate you watching and the feedback!
@michaelwong1908
@michaelwong1908 3 жыл бұрын
That's clearly explained! Wish I have learnt this earlier.
@CodeOpinion
@CodeOpinion 3 жыл бұрын
I guess I should of posted it sooner 😀. Glad it helped.
@Eugene.g
@Eugene.g 3 жыл бұрын
I wish my code was that clean and readable
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Glad you thought it was readable 😀 I actually left some of the code without using some of the new C# features to not throw people off.
@JohnnysaidWhat
@JohnnysaidWhat Жыл бұрын
These videos are where you go when you fight the final boss of EDD. So good but so technical.
@williamsbotchway2471
@williamsbotchway2471 Жыл бұрын
Hi Dereck i am new to ddd but i have question on the video. Since u are passing a collection of stops to the constructer of the shipment aggregate, it means clients other than the shipment aggregate can call both the arrive and isComplete methods thereby resulting in inconsistent state, by passing the rules defined in the shipment aggregate? Does this means a refinement of what is needed to enforce the invariant is needed? Pls answer on this. Also one general rule is that entities inside an aggregate can only be reference by other aggregate by holding a transient copy of these entities. I think passing a collection of stops as shown in the videos violate this general rule. however domain services can be used to defined previousStopAreNotDeparted and used as client in stop which should be treated as aggregate. If this approach is corrected should we have two distinct aggreagete for PickupStop and DeliveryStop. Again i am a novice to ddd so please advice. Thank u.
@MrSpyTubes
@MrSpyTubes 2 жыл бұрын
🙏 thanks for your great work.
@vakul_18k55
@vakul_18k55 2 жыл бұрын
Inside the stop class. We have sequence as primitive. Should we create it as a value type? From what I have seen DDD says we should not have primitives
@kylegivler8372
@kylegivler8372 9 ай бұрын
Thanks!
@CodeOpinion
@CodeOpinion 9 ай бұрын
Thank you!
@ivanmiroshnichenko4299
@ivanmiroshnichenko4299 2 жыл бұрын
As far as I understood, if I have a 'manager' class which has a couple of methods such as 'Run()' something or 'Stop()' something is an aggregate class, isn't it?
@CodeOpinion
@CodeOpinion 2 жыл бұрын
That's not enough for me to define if it's an aggregate. An aggregate is a collection of related objects that form a consistency boundary.
@SaudBako
@SaudBako 2 жыл бұрын
Instead of throwing exceptions on rule violations, is there any harm to make Shipment expose a single function, Advance(), which decides which stop to advance and how to advance (i.e. which Stop method to call) based on their states? If this over-simplified interface guarantees enforcing business rules, wouldn't these exceptions be unnecessary burden on Shipment consumers and tests?
@CodeOpinion
@CodeOpinion 2 жыл бұрын
No you absolutely could do that since there's a single progression. The issue is if you're in a concurrent environment where many different users could be trying to perform an action. You wouldn't want one to do Advance() at the same time as another. There you would obviously need to do some optimistic concurrency if you choose to go the Advance() route.
@thedacian123
@thedacian123 2 жыл бұрын
Spotting boundaries is a complicated stuff,and DDD in general which leads to domain experts/analists comitmment.But what should we do if business people are not too cooperant?Thanks
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Ya it's a good question and one I've gotten over the years. Anything is difficult if you aren't going to have buy in and cooperation.
@futurexjam2
@futurexjam2 Жыл бұрын
you can apply BPM(business process management) approach. By BPM approach you can easily change the flow between states even binding coniditional transitions.
@tarreislam
@tarreislam 2 жыл бұрын
Thanks
@lost-prototype
@lost-prototype 2 жыл бұрын
Great video! A quick question... Do you ever create extension methods on generic collection types of your domain models to represent certain filters or operations?
@CodeOpinion
@CodeOpinion 2 жыл бұрын
I'm trying to think if I have for domain objects. I don't think so but I generally create extension methods when I don't want to pollute the focus of the initial API. Usually for some specialized reason.
@alfonsdeda8912
@alfonsdeda8912 6 ай бұрын
Hi Derek, i use ef core for my database and in one service class i should update two entities in the same transaction, for the ofher entity i already have the independent service that could the operation that i would need but it must be done in the same transaction, should i implement the unit of work pattern or is ok to use directly the dbcontext even for an operation that is already implemented separately? I hope it is clear. Thanks in advance.
@CodeOpinion
@CodeOpinion 6 ай бұрын
EF Core Context is a unit of work. Hence you can update multiple DbSets within the same transaction.
@alfonsdeda8912
@alfonsdeda8912 6 ай бұрын
@@CodeOpinion thank you for response, sorry, I have not mentioned one important thing,the relationship is one to many and I want to add an object in the many service, should I do all method to add those many objects in the one side service, because I have many relationship one to many with the same one entity, the one could be an aggregate but the one side service would be too big If I implement all many entities operations , any suggestion?
@snowglider400
@snowglider400 2 жыл бұрын
@CodeOpinion why you didn't use state machine ?
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Just an example. I have other videos where I do.
@dansharpe4535
@dansharpe4535 3 жыл бұрын
i have a quick question around the Stop classes, in terms of other stop information, location, opening times etc, would you have another, fuller entity/aggregate? and if the shipment required things like opening times for its business logic (eg to check its open on the shipment day), how would you do this? would you load the full entity/aggregate and pass this information in as part of the command or have i missed a concept?
@CodeOpinion
@CodeOpinion 3 жыл бұрын
So for me it depends if you need that data for invariants (business logic). If you don't, my aggregates are generally for write/command purposes, not queries. If that's the case, then if you don't need it for invariants, then you don't need it in the aggregate. If you do need other data that isn't apart of the aggregate, and you don't think it should be apart of it (opening times), then you can always pass that data (or double dispatch) when you call a method on the aggregate that needs it eg, ArriveStop(PlaceValue) or ArriveStop(stopId, Places.GetOpeningTimeDelegate) or ArriveStop(stopID, IPlaces)
@dansharpe4535
@dansharpe4535 3 жыл бұрын
@@CodeOpinion thanks for that reply, it really helps, sometimes i just struggle a bit with what ok to pass into a method within your aggregate (like additional info to help with business logic) or does that then create a dependency on something outside of the aggregate?
@CodeOpinion
@CodeOpinion 3 жыл бұрын
Nothing wrong with passing what you need so as long as you understand the coupling. Double dispatch as well isn't inherently bad.
@dansharpe4535
@dansharpe4535 3 жыл бұрын
@@CodeOpinion that makes sense, as if the call to get opening times fails, then you cant validate your business logic at that point but the logic is still encapsulated within the aggregate :)
@13odman
@13odman 6 ай бұрын
Didn’t you say that an anemic domain model is fine if you know it is?
@CodeOpinion
@CodeOpinion 6 ай бұрын
Absolutely. It has utility if you don't need a domain model and you realize that it's not a domain model.
@danflemming3553
@danflemming3553 2 жыл бұрын
Even with the Shipment aggregate root, the PickupStop and DeliveryStop classes still have public methods which can change the statuses independently. How to solve this? Thanks!
@CodeOpinion
@CodeOpinion 2 жыл бұрын
If you want to go down the road of locking it down, use the appropriate access modifiers. TBH, I don't concern myself with it too much because the stops aren't directly accessible outside the aggregate. They are generally passed in via the constructor from a repository.
@danflemming3553
@danflemming3553 2 жыл бұрын
@@CodeOpinion Thanks but it's not that simple. Adding access modifiers means you won't be able to actually call methods on those classes. Maybe I am missing something, but it's not simple. Aggregate roots even with the latest EF Core is not simple to achieve if you really apply encapsulation and private access modifiers. Have you tried it?
@CodeOpinion
@CodeOpinion 2 жыл бұрын
@@danflemming3553 No I don't with EF. I distinguish between data models and domain models and I don't try to make both be the same thing. Generally I have an aggregate root that in the constructor takes in the appropriate data models. This aggregate root is built by a repository that gets the data models out to pass them in. So to have public setters on the data models (EF) is irrelevant because nothing besides within the aggregate root has access to those and it's the only thing making changes to the data (EF) models. I talk about this more in this video: kzbin.info/www/bejne/faW6h3qApZVpZ6M
@williamsbotchway2471
@williamsbotchway2471 Жыл бұрын
@@CodeOpinion I still have concerns with this. how is it possible to hydrate stops from a database with a respository. Repositories on only uses aggregate root not entities or aggregate for database rehydration. I am right? Pls advice.
@MsTArray
@MsTArray 2 жыл бұрын
isn't this somehow related to state machines?
@CodeOpinion
@CodeOpinion 2 жыл бұрын
The example is, yes.
@dayanshuwang2508
@dayanshuwang2508 2 жыл бұрын
Hey Derek, can you make these videos private and charge bit money? otherwise junior developers gonna catch up so quickly, we need our job to be safe 😂
@CodeOpinion
@CodeOpinion 2 жыл бұрын
Well we all learn various things at different points in our career path. Hoping some of the stuff I've run into along the way helps others regardless of where they are. Appreciate the comment!😊
@dayanshuwang2508
@dayanshuwang2508 2 жыл бұрын
engineers are naive, how many open source project geek cant even get fund or been turned down by big company that actually using their projects - the world is never fair and developers so easy to be taken advantage of since their logical and true/false thinking 😂 intellectual property/experience are easily copied or stolen, you have really reduced the learning path for junior jumping on a senior path which the older developers took a long way to arrive, mate 😂
@weraponpat1913
@weraponpat1913 2 жыл бұрын
why didn't i found this early so i don't have to refactor my code :(
@alvaromp1106
@alvaromp1106 2 жыл бұрын
The example is too complicated. It would have been better to pick up a simpler example to illustrate... I mean, after all the idea was to teach about aggregation right? Why make everything more confuse with deliveries, stops, shipment? Thanks anyway..
@CodeOpinion
@CodeOpinion 2 жыл бұрын
I also get comments that my examples are to simple. The challenge is finding the balance between complex enough examples that illustrate the need for certain design patterns and simple enough that the reader/watcher doesn't need deep understanding of the problem domain.
@yurimelo3404
@yurimelo3404 Жыл бұрын
I have a question about these three status: InTransit, Arrived and Departed. They are related to Pickup and also to Delivery, okay? I'll improve my question with an example to see if I understood it well. Let's say that I ordered a pizza at my house. So the order has been processed and the pizza is ready to be delivered to my house. So the food app has a delivery person responsible for delivering to my house, which, in turn, needs to go to the restaurant to pick up the food and then take it to my house. With this example there are several status changes. Which of the two scenarios is what the video is trying to say? Or is it another? (Note that I may have misunderstood.) First scenario: - Delivery guy going to the restaurant - Status changed to InTransit - Delivery guy took my food - Status changed to Arrived - Delivery guy left with my food - Status changed to Departed - Deliverer is on the way - Status changed to InTransit - Deliver arrived at destination - Status changed to Arrived - Delivery person successfully dropped off the food - Status changed to Departed Second scenario: - Delivery guy going to the restaurant - Status changed to InTransit - Delivery guy got my food - Status not changed [InTransit] - Delivery guy left with my food - Status not changed [InTransit] - Deliverer is on the way - Status not changed [InTransit] - Deliver arrived at destination - Status changed to Arrived - Delivery person successfully dropped off the food - Status changed to Departed
@CodeOpinion
@CodeOpinion Жыл бұрын
The first is correct.
@yurimelo3404
@yurimelo3404 Жыл бұрын
@@CodeOpinion Thank you!!! Your videos have changed my way of thinking about architecture by using Domain-Driven Design.
Highly COHESIVE Software Design to tame Complexity
9:01
CodeOpinion
Рет қаралды 13 М.
Don't be fooled! That's NOT an Aggregate in Domain Driven Design
10:12
Zombie Boy Saved My Life 💚
00:29
Alan Chikin Chow
Рет қаралды 24 МЛН
Happy birthday to you by Tsuriki Show
00:12
Tsuriki Show
Рет қаралды 11 МЛН
Magic trick 🪄😁
00:13
Andrey Grechka
Рет қаралды 51 МЛН
How to (and how not to) design REST APIs
14:28
CodeOpinion
Рет қаралды 52 М.
Domain Events and  Event Sourcing go hand in hand? Not Exactly!
9:03
Stop Calling Your API a "REST API"
17:42
Amichai Mantinband
Рет қаралды 16 М.
Keep your project structure simple!
15:08
CodeOpinion
Рет қаралды 17 М.
Is an ANEMIC Domain Model really that BAD?
10:36
CodeOpinion
Рет қаралды 17 М.
Did we learn anything from Microservices? (Part 1)
15:51
CodeOpinion
Рет қаралды 7 М.
My TOP Patterns for Event Driven Architecture
10:45
CodeOpinion
Рет қаралды 30 М.
How to design great Aggregate Roots in Domain-Driven Design
11:30
Milan Jovanović
Рет қаралды 11 М.
Самый дорогой телефон 2000х
0:54
МАДНЕСС
Рет қаралды 2,4 МЛН
На что способен ваш компьютер?
0:34
ноутбуки от 7.900 в тг laptopshoptop
0:14
Ноутбуковая лавка
Рет қаралды 4,1 МЛН
Nokia imba #trollface #sorts
0:31
SodnomTsybikov
Рет қаралды 6 МЛН