Get the source code for this video for FREE → the-dotnet-weekly.ck.page/entity Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@flobuilds2 жыл бұрын
I'm glad i found your channel. I hate all these "beginner" or standard videos where they always show code that would never be in production but this is some quality stuff thanks 💯
@MilanJovanovicTech2 жыл бұрын
This is kind of the gap that I also noticed, and one I'm trying to fill. By the end of this series we will have created a nice production ready application 😁
@flobuilds2 жыл бұрын
@@MilanJovanovicTech thanks for the great work seeing forward to the end and the stuff that comes after that😃 im currently building a production ready system for our startup but im just learning by doing and if you don't find good articles or videos to learn the good stuff you have a big problem
@MilanJovanovicTech2 жыл бұрын
@@flobuilds Anything that would benefit you in particular?
@flobuilds2 жыл бұрын
@@MilanJovanovicTech at the moment im building the complete auth server with all the user functionalities, refresh tokens etc. But after that service i want to implement all other functions with microservices for our system because its modern and will later be way easier to do maintenance. And it would be nice to find something in depth about microservices like the complete implementation with docker/kubernetes and the code itself and the api gateways and maybe backend communication like rabbit mq
@ZeeshanAli-ll6ki2 жыл бұрын
@@MilanJovanovicTech Can you add implementing auth functionality along with refresh token in your future videos along with concepts like mapping the data from jwt token to profile class and then using that class inside other endpoints.
@nicholasslodki703 Жыл бұрын
Your monolog with these is excellent and demonstrates a masterful command of both English and the rest of this stuff.
@MilanJovanovicTech Жыл бұрын
Thanks a lot :)
@chrismingay60052 жыл бұрын
you've got a great way of explaining things. I'm by no means a beginner anymore but your videos are always a great refresher, I really appreciate your effort with these
@MilanJovanovicTech2 жыл бұрын
I appreciate that Chris, thank you!
@armanbecirovic22384 ай бұрын
Have to admit this CA&DDD series is fantastic! Very well explained step by step with logical explanation and why something is a good practice. I started to like DDD just by watching your videos. Thank you Milan! 👏💪
@MilanJovanovicTech4 ай бұрын
Glad you enjoyed it!
@kinggrizzly132 жыл бұрын
I love the simplicity of following YAGNI principle for your example. Many books and examples throw you a lot of boilerplate code that may not be necessary when learning DDD techniques. Thanks for sharing.
@MilanJovanovicTech2 жыл бұрын
I had to follow those many book and examples to be able to explain it simple like this 😅 Hopefully this speeds up others learning about DDD
@andergarcia11153 ай бұрын
I hope to be like you one day. Thanks for being an inspiration
@MilanJovanovicTech3 ай бұрын
You can do it!
@modernkennnern Жыл бұрын
3:10 This might be late, but as long as you only initialize it in the constructor you don't even need a setter. `public Guid Id { get; }` is enough.
@MilanJovanovicTech Жыл бұрын
True
@Eamo-212 жыл бұрын
Awesome Milan! I see you on Twitter often but not KZbin
@MilanJovanovicTech2 жыл бұрын
Hopefully the algo starts showing me some love 😁
@sushilb79942 жыл бұрын
Nice video, Milan. Your videos are awesome because you keep it simple and go over from basic to advance concepts. Love this format. Keep it up!!!
@MilanJovanovicTech2 жыл бұрын
Thank you, I'm really glad you are liking the channel so far. More great videos are coming 😊
@nickolaki2 жыл бұрын
You cheeky boy putting this out today rather than tomorrow. 😉Great job Milan!
@MilanJovanovicTech2 жыл бұрын
But I am aiming for Tuesday-Thursday anyhow 🤷♂️
@tidianediallo61992 жыл бұрын
😊😊
@ugochukwuumerie63782 жыл бұрын
Awesome! Keep 'em coming. I see people using like an aggregate root to define the entity id
@MilanJovanovicTech2 жыл бұрын
I think the line is kind of blurry between them. I prefer not applying the AggregateRoot pattern, as I tend to end up with big aggregates with a lot of logic. Also, just because the pattern exists doesn't mean you have to use it. 😁
@ugochukwuumerie63782 жыл бұрын
@@MilanJovanovicTech thanks alot 🙏, I appreciate, its much more clearer now
@ipelengmekgwe8347 ай бұрын
Your videos are so informative, thank you!
@MilanJovanovicTech7 ай бұрын
You are so welcome!
@anthonytrad2 жыл бұрын
Great video, a small heads-up nevertheless: Using Guids directly for ids may be considered as a primitive type obsession... You're setting the fundamentals and you didn't talk about value objects yet, but I think this should be mentioned because It will affect your base Entity implémentation. I think PTO is a key concept if we're doing DDD soo that's just my thoughts.
@MilanJovanovicTech2 жыл бұрын
That's a great observation. I'm covering ValueObjects in one of the future videos, and also talking about Primitive Obsession. However, I didn't touch on strongly typed Ids. I'm thinking of making a separate video on that topic, now that you mentioned it.
@tiagocandeias39692 жыл бұрын
If we go down the "Primitive type obession" rabit hole you wont even have strings and int in the entities :) Or is it anything specific for GUID's that I'm missing
@anthonytrad2 жыл бұрын
@@tiagocandeias3969 I was mainly referring to strongly type IDs. We don't apply PTO on every property, the FirstName for example can stay a string but if you were to add an address then it might be better as a value object. Applying it everywhere would be insane;)!
@kinggrizzly132 жыл бұрын
Totally agree, as I’d make my Id a ValueObject as well.
@MrKlyushin Жыл бұрын
Hello, Milan, You made your Gathering class as sealed. My sonarsource tells me of a bad smell RSPEC-4035 Tells me - Classes implementing "IEquatable" should be sealed Is it okay if I remove sealed because I need to have inheritance? And I also don't get if a "domain layer" can have an interface folder for interfaces for entities. Example: I've got hierarchy: BaseMaterial -> Material, PackMaterial and all of them implement IMaterial interface in which I guarantee that all classes that implement it have some fields and some methods I expect them to have.
@MilanJovanovicTech Жыл бұрын
If you need inheritance, of course
@MrKlyushin Жыл бұрын
@@MilanJovanovicTech thx! 👍
@tidianediallo61992 жыл бұрын
I am very happy to find this channel and the explanations are clear and precise and I look forward to the next videos. A big thank-you. Just a question M Milab: How do you choose the naming of the folders and what they should contain, for example the primitive folder?
@MilanJovanovicTech2 жыл бұрын
Hi, and welcome to the channel! 😁 Copying the answer from another thread: So using "Abstractions" and "Primitives" for these kinds of common/base types is something I picked up from Microsoft. If you notice how they create their namespaces, interfaces and types are usually defined in a namespace ending with either ".Abstractions" or ".Primitives"
@coding-in2 жыл бұрын
Yu are right! He's keep to explain what he's writes..
@9_vko2 ай бұрын
Nice tutorial! On the other hand I would add more details information about what's difference between Anemic Domain Model and Rich Domain Model approaches. In which case we need to pick the Anemic Domain Model or Rich Domain Model ?
@MilanJovanovicTech2 ай бұрын
I made a separate video on that
@9_vko2 ай бұрын
@@MilanJovanovicTech Awesome! 😎
@سهیلداودی-ص1ف2 жыл бұрын
Why do We have to check equality between two objects in DDD, Thanks for video and please keep posting videos
@MilanJovanovicTech2 жыл бұрын
How else would we know if two entities are the same?
@garethcraig89026 ай бұрын
Really great video. My only concern is the use of Guid's. I work in the online gaming industry and we have an extremely high transaction rate, thousands of bets a minute. Guids have not fared very well and we have been actively removing them for smaller data types. Not sure how we would apply this, with say a INT or Short data type.
@MilanJovanovicTech6 ай бұрын
You probably don't generate those values client-side?
@ujuzitek301 Жыл бұрын
Hi Milan, what is the logic by multiplying the GetHasCode method by a prime number?
@MilanJovanovicTech Жыл бұрын
Provides a more even distribution of the hash code, nothing fancy though
@Yosso1172 жыл бұрын
Братан, хорош, давай, давай, вперёд! Контент в кайф, можно ещё? Вообще красавчик! Можно вот этого вот почаще?
@MilanJovanovicTech2 жыл бұрын
More about DDD or more about Entities?
@LilPozzer6 ай бұрын
extreme code
@paulbarton22802 жыл бұрын
Will you be covering Aggregates? It seems even with this simple domain, if for example a Gathering was to be canceled this would effect other Entities/Value Objects.
@MilanJovanovicTech2 жыл бұрын
I'm still uncertain about that one Paul. Not sure if I just want to continue with Domain Events, or tackle it from an Aggregate perspective. Going to decide this weekend anyway 😁
@paulbarton22802 жыл бұрын
@@MilanJovanovicTech I understand. Is there a reason you did not make the Id property of your Entity class a Value Object?
@krccmsitp28842 жыл бұрын
@@paulbarton2280 Guid is a struct which already has the behavior the Value Object pattern would give.
@MarincaGheorgheАй бұрын
A question. Why would you need to compare entities in your domain: collision or what? Who would need to use equality on these ?
@MilanJovanovicTechАй бұрын
Semantics
@huynhtriet444 Жыл бұрын
Hi Milan, really great information here! Just one question when you implement the Equal(Entity? other) method. Since you already have the Equal(object? obj) method, can't you utilize this when you create the Equal(Entity? other) as well? Something like this " public bool Equals(Entity? other) { return Equals(other); }". I want to know if this is the same or I am missing something. Thank again for your work!
@MilanJovanovicTech Жыл бұрын
You'd have to cast it to an object, so that's one downside, otherwise it's possible
@vertikalniserklaz8694 Жыл бұрын
This is cool and very helpful, however, I haven't found an explanation in any of your videos on how to perform entity validation that require any interaction with DB (e.g. duplicate user name). Naturally, this type of validation should be encapsulated in an entity but, of course, you won't inject a repository into an entity to check duplicates.
@MilanJovanovicTech Жыл бұрын
There's a video on user registration and validating duplicate emails that I'm sure you'll enjoy
@MilanJovanovicTech Жыл бұрын
4 Ways To Do Email Uniqueness Check, let me know what you think after watching
@vertikalniserklaz8694 Жыл бұрын
@@MilanJovanovicTech as long as we stick to the previously defined standard, it is fine. I found many times people are doing validation that involves DB calls in DomainService class which leads us to an anemic domain model (entity), though sometimes. Btw, can you point to the video where you explained CreateMemberCommandHandler and Domain Services?
How would this approach change if you are using strongly typed IDs for your entities. Would you still need this base Entity functionality?
@MilanJovanovicTech Жыл бұрын
It becomes quite a bit verbose, honestly. Entity has to be generic, and you need to solve strongly typed ID equality as a generic argument. Amichai had an interesting take in a recent video
@tanvirarjel2 жыл бұрын
Good work! MIlan, Continue please! However, I have a question. What is your thought process behind naming the folder 'Primitives'?
@MilanJovanovicTech2 жыл бұрын
That's a great question. So using "Abstractions" and "Primitives" for these kinds of common/base types is something I picked up from Microsoft. If you notice how they create their namespaces, interfaces and types are usually defined in a namespace ending with either ".Abstractions" or ".Primitives"
@tanvirarjel2 жыл бұрын
@@MilanJovanovicTech Good spot!
@aseneda2 жыл бұрын
Great content and didactic Milan, congrats! Could I suggest a Builder creational pattern in case of complex Entity. Next video will be Object Value :) ? Best regards
@MilanJovanovicTech2 жыл бұрын
Next video will be Domain validation. Followed by Value Object, Aggregates, Domain Events... 😁
@imaynedlog9628 Жыл бұрын
Why do you need init in Entity class? Because we set ID using constructor anyway, we just need readonly ID property, don't we?
@MilanJovanovicTech Жыл бұрын
Make it easier when materializing entity
@afermeherremova5672 Жыл бұрын
If all my entities use different data types for their ID, is it acceptable to convert the Entity class to a generic type?
@MilanJovanovicTech Жыл бұрын
You can - but beware of how you will use that Entity in any generic context
@zheniachubarov338410 ай бұрын
Does EF Supports init modifier?
@MilanJovanovicTech10 ай бұрын
Yes
@pigrebanto11 ай бұрын
Good stuff! Why you have 2x Equals methods in the Entity class? isn't the one on the Entity (Equatable interface) enough?
@MilanJovanovicTech11 ай бұрын
One is object.Equals and one is IEquatable.Equals
@dhanushshetty78402 жыл бұрын
Is there going to be more refactoring so that we can execute moq frameworks to unit test?
@MilanJovanovicTech2 жыл бұрын
I will tackle testing at some point for sure.
@dhanushshetty78402 жыл бұрын
@@MilanJovanovicTech thanks Milan
@ivandrofly Жыл бұрын
thanks
@MilanJovanovicTech Жыл бұрын
You're welcome!
@sinafallahpour2626 Жыл бұрын
very good video
@MilanJovanovicTech Жыл бұрын
Thanks!
@jimkoro6642 жыл бұрын
Hi Milan. Why not let the base Entity instantiate the Id in the ctor or the prop. What's the benefit of passing it via ctor parameter only to use .NewId in every case?
@MilanJovanovicTech2 жыл бұрын
You are going to get some funny behavior if you use EF as your ORM. EF calls the constructor that it deems appropriate when materializing entities. So that ctor that sets the Id may get called on every read from the DB, so you will end up with a random Id on each try. Be careful with that one.
@HajvazS2 жыл бұрын
Hi Koro, you can do this, but you have to make the set of the Id property public, so ef core will overwrite the instantiated Id whe materializing entities. Maybe you can try to have two constsructors, one for creating new entities, and the other one for existing entities and test how EF is handling this.
@bohdankatrychenko2479 Жыл бұрын
Aren't the if statements when you compare obj.GetType() and that object is an Entity check the same thing?
@MilanJovanovicTech Жыл бұрын
What guarantees that they are the same type?
@bohdankatrychenko2479 Жыл бұрын
@@MilanJovanovicTechI'm not completely sure, but I think that GetType comparison guarantees that they're the same type. And the second if statement is not really needed, you could just type cast the object to the entity like this: Entity entity = (Entity)obj
@iliyan-kulishev2 жыл бұрын
I started watching your videos all the way from the oldest. I really like what DDD brings, but can't we avoid having ids as Guids ? Can't I just rely on DBMS and the autoincrement mechanism there ?
@MilanJovanovicTech2 жыл бұрын
Absolutely, there's no reason you can't go with that. This was just a design decision at the time
@ivandrofly Жыл бұрын
1:03 - Definition* of Entity
@MilanJovanovicTech Жыл бұрын
Indeed
@microtech2448 Жыл бұрын
Can we make an entity that has a generic type rather than Guid? Because some entities may have primary keys as integer, some may have bigint, some may have Guid etc.. if yes, then how. Thanks!
@MilanJovanovicTech Жыл бұрын
Of course, just more boilerplate
@microtech2448 Жыл бұрын
@@MilanJovanovicTechcan you post something on this as community post?
@MilanJovanovicTech Жыл бұрын
@@microtech2448 Sure 😁
@microtech2448 Жыл бұрын
@@MilanJovanovicTech thanks 🙂
@mahmoudalballah3387 Жыл бұрын
Awesome!
@MilanJovanovicTech Жыл бұрын
Should I do more DDD content? 😁
@imaynedlog9628 Жыл бұрын
Also, why do you use an "Entity?" This is a class, so it can be null anyway? Or it for other developers? Your VS doesn't recommend you remove "?" because this isn't a value object?
@MilanJovanovicTech Жыл бұрын
Just making things explicit
@imaynedlog9628 Жыл бұрын
@@MilanJovanovicTechThank you very much for answering)
@nikolaignjatovic67882 жыл бұрын
Nice video. Why 41?
@MilanJovanovicTech2 жыл бұрын
41 is a prime number. When multiplying with a prime number you are more likely to produce an even distribution of hash codes across hash buckets. Resulting in less hash colisions.
@nikolaignjatovic67882 жыл бұрын
@@MilanJovanovicTech Thank you Milan. :)
@vikontart2 жыл бұрын
@@MilanJovanovicTech I think that we need to extract this magic number 41. Create a const variable and describe it. What do you say?
@sinafallahpour2626 Жыл бұрын
im from iran and i cant pay $ for you from iran . how to access the code . I realy watch full of your video. andnow inee then code but I canr pay for this because im from iran what should I do?
@MilanJovanovicTech Жыл бұрын
I'm not sure what we can do in that case. I think Patreon should support local currencies also, as long as you have a valid bank card.
@ravindranathwi2 жыл бұрын
Thanks for the video got a question whats the harm in putting interface over these entities. Other than multiple possible implementations. Because entities take out the testability can't really substitute or mock one of these for testing. How would you test when entity grow it becomes painful
@MilanJovanovicTech2 жыл бұрын
Why would you ever want to mock an entity?
@ravindranathwi2 жыл бұрын
@@MilanJovanovicTech Example I have OrderProcessHandler which takes an orderRecoverRequest. Now behaviour of the handler is. it should first load order then it should run order through a rule engine if order is valid then it should update status and send then email. Now without interface over entity you would have to create the entity in valid state run the rules engine that will raise all events and then only you can check email sent or not. So that valid state arrange is hard to setup. In interface over entity scenario I would just AutoData ask the mock factory to give me an intance and mock the other events which states that rules passed then check sendEmail is called.
@ravindranathwi2 жыл бұрын
@@MilanJovanovicTech also that enables whether entity method has been called from handler testing. Appreciate your input on this
@bmassioui2 жыл бұрын
Entities vs aggregates in a phrase.
@MilanJovanovicTech2 жыл бұрын
Which is cooler?
@МихаилСтепанов-л3х2 жыл бұрын
You create 2 Equals. why not Equals( obj ) => Equals( obj as Entity )? No code duplicates. You check GetType == GetType and obj is Entity. @this is child of Entity. obj has equal type. so obj is Entity. So half of your code is garbage. ==: if first is null and second is null => null == null => true. but your code returns false. 1 small class full of thrash. Good job boy.
@MilanJovanovicTech2 жыл бұрын
Thanks!
@ramakrishna-ms7ly4 ай бұрын
use light screen your tool in black mode and video is not clear
@MilanJovanovicTech4 ай бұрын
Thanks
@ahmedameen210 ай бұрын
Try to focus more on concept rather than code
@MilanJovanovicTech10 ай бұрын
Dry
@anomalii77202 жыл бұрын
Why????? Hi, do you want to be a programmer? I will make it as hard as possible for you okay? Why? I don't know, that's just the way I am.