You're building a gold mine with this series. I can only imagine someone in the future finding this complete playlist and finally undestanding all these topics. Keep it up!
When you were talking about ValueObject concept in previous vids, I was thinking that your were gonna just use record type for this one property - Id. Now when you show how to implement it it is full blown class, so I wonder what are the benefits to go with class compared to record? Wouldn't record be much simpler and less boilerplate?
Hey, Amichai! Been watching your vids lately. I've been doing dotnet backend for 2 years now, but I'm primarily a NestJS/NodeJS backend developer. And I must say that your insights greatly gives me an outside perspective in me designing backend architecture, and it also inspires me to pursue to transition to Dotnet primarily (since your videos are making dotnet development cool!). I hope you could make videos (just hoping haha) regarding showing the advantages in setting up Models with your implentation versus to the basic setups in Models (without the AggregateRoot, Entity, ValueObject). And more power to you!!
Finally! Great video. You're such a tease with these quick vids, any chance you are going to do some longer format videos? Love your content, keep it up.
6:04 Suppose we want to use just a Guid as TId. Then, the Equals method would return true if any entities have the same Id, even if those entities were different. This approach forces you to use ValueObjects as an entity id. It's worth to keep that in mind
Nice tutorial, but I have 3 questions: May we define our value objects like record? It would be better to define that the object id implements Iequatable, wouldn't it? (Question to the previous video) If we have an aggregate that has 2 large collections of entities inside, is it better to define them as aggregates too, despite the fact that they are not used anywhere else?
Thanks, Danil. 1. Records for ValueObjects - Yes and no. Vladimir Khorikov has a good blog I would suggest reading: enterprisecraftsmanship.com/posts/csharp-records-value-objects/ 2. Yes. Actually, in our project, it would be better to put a constraint that the id implements ValueObject since that's the approach we'll take. 3. As a rule of thumb - yes. Especially if you think about what happens with these large aggregates when multiple commands try to update the same aggregate simultaneously.
@@amantinband With regard to IEquatable, my understanding is that it is used to prevent boxing/casting to object. However, public bool Equals(ValueObejct? other) { return Equals((object?)other); } does exactly this. Therefore, any performance benefits that could have been made are now lost. Or, have I misunderstood something? Thanks. P.s. I'm enjoying all of videos 👍
Didn't like the points about `Weight` and `with`. We can put validation in the set/init so that it can't be bypassed. And we can just implement another method for Equals with precision.
Hey Amichai great series ! I have a question : in value object when defining == operator we use equals method that takes 2 arguments. But we never defined a method that takes 2 arguments inside that class. Does it take that method from somewhere else, or how does that work ? Thanks
And also we are overriding the equality operator since 'object' type which is the parent of all objects except primitive types has a default implementation for == which compares the objects by reference and we override it since we want to compare by value. Hope that helps.
@@uzayrsyed6293 Hey thanks for the answer. It does help, but why in the == operator we use : return Equals(left, right) instead of return left.Equals(right)?
@@fhwroungwnwget3705 When I look at the Object.cs metadata file the Equals method with two objects as parameters cannot be overridden. We are overriding the virtual Equals method with one object parameter and this is the logic we want to use for our == and != parameters. Seems like left.Equals(right) should be used unless Equals(left, right) uses left.Equals(right) internally
EDIT: NVM I realize that you are sealing the class the implements the abstract class. Should we implement IEquatable in a non sealed abstract class? Would it be better to implement IEqualityComparer instead?
@amantinband I am wondering why not use a record for the Value Object base class. I know this video is a year old, but still was wondering what your take, or anyones take on this is?
Am I missing something here? Why wouldn't you use a record here, that would give you all the equality stuff for free. But I have to confess I haven't watched the previous videos; this one just popped up in RUclips's suggestions.
Yes and no. Check out this blog post by Vladimir Khorikov where he shows some pros and cons enterprisecraftsmanship.com/posts/csharp-records-value-objects/
You're building a gold mine with this series. I can only imagine someone in the future finding this complete playlist and finally undestanding all these topics. Keep it up!
so yea here i am!!!! hahah
Hey! I'm someone from the future and indeed is pure gold :)
Cheers!
Nice touch with Entity, and I wasn't aware of the notnull generic constraint 💯
Hi Milan! ^^
When you were talking about ValueObject concept in previous vids, I was thinking that your were gonna just use record type for this one property - Id. Now when you show how to implement it it is full blown class, so I wonder what are the benefits to go with class compared to record? Wouldn't record be much simpler and less boilerplate?
this is exactly what i was thinking
Hey, Amichai! Been watching your vids lately. I've been doing dotnet backend for 2 years now, but I'm primarily a NestJS/NodeJS backend developer. And I must say that your insights greatly gives me an outside perspective in me designing backend architecture, and it also inspires me to pursue to transition to Dotnet primarily (since your videos are making dotnet development cool!).
I hope you could make videos (just hoping haha) regarding showing the advantages in setting up Models with your implentation versus to the basic setups in Models (without the AggregateRoot, Entity, ValueObject).
And more power to you!!
Finally! Great video. You're such a tease with these quick vids, any chance you are going to do some longer format videos? Love your content, keep it up.
Hahah thanks silvertek. Some of the videos coming up will be longer 👍
This video broke my brain but in a good way! Still a lot to learn! Thanks for the video!
Great video, I'm learning a lot from this series
Awesome 💪
keep the awesome videos coming! your videos are top notch! right up there with the likes of Chapsas!
Thanks 🫶
Great tutorials man, thanks a lot
6:04
Suppose we want to use just a Guid as TId. Then, the Equals method would return true if any entities have the same Id, even if those entities were different. This approach forces you to use ValueObjects as an entity id. It's worth to keep that in mind
I love this series. Thanks for sharing your knowledge.💯
Loved the explanation!
Nice tutorial, but I have 3 questions:
May we define our value objects like record?
It would be better to define that the object id implements Iequatable, wouldn't it?
(Question to the previous video) If we have an aggregate that has 2 large collections of entities inside, is it better to define them as aggregates too, despite the fact that they are not used anywhere else?
Thanks, Danil.
1. Records for ValueObjects - Yes and no. Vladimir Khorikov has a good blog I would suggest reading: enterprisecraftsmanship.com/posts/csharp-records-value-objects/
2. Yes. Actually, in our project, it would be better to put a constraint that the id implements ValueObject since that's the approach we'll take.
3. As a rule of thumb - yes. Especially if you think about what happens with these large aggregates when multiple commands try to update the same aggregate simultaneously.
@@amantinband Thanks!)
@@amantinband With regard to IEquatable, my understanding is that it is used to prevent boxing/casting to object. However,
public bool Equals(ValueObejct? other)
{
return Equals((object?)other);
}
does exactly this. Therefore, any performance benefits that could have been made are now lost. Or, have I misunderstood something?
Thanks. P.s. I'm enjoying all of videos 👍
Didn't like the points about `Weight` and `with`.
We can put validation in the set/init so that it can't be bypassed.
And we can just implement another method for Equals with precision.
your are so amazing thank you :)
Hey Amichai great series ! I have a question : in value object when defining == operator we use equals method that takes 2 arguments. But we never defined a method that takes 2 arguments inside that class. Does it take that method from somewhere else, or how does that work ? Thanks
That's the magic of the operator keyword applied against ==, the lhs and rhs together make two parameters in total.
And also we are overriding the equality operator since 'object' type which is the parent of all objects except primitive types has a default implementation for == which compares the objects by reference and we override it since we want to compare by value. Hope that helps.
@@uzayrsyed6293 Hey thanks for the answer. It does help, but why in the == operator we use : return Equals(left, right) instead of return left.Equals(right)?
@@fhwroungwnwget3705 When I look at the Object.cs metadata file the Equals method with two objects as parameters cannot be overridden. We are overriding the virtual Equals method with one object parameter and this is the logic we want to use for our == and != parameters. Seems like left.Equals(right) should be used unless Equals(left, right) uses left.Equals(right) internally
@@uzayrsyed6293 My thoughts exactly. Thanks for clarification
Shouldn't Entity have a constraint on type TId to be ValueObject?
Thank you!
Shalom, ahi ) I've seen in another video your AggregateRoot is using complex AggregateRootId - could you explain why?
EDIT: NVM I realize that you are sealing the class the implements the abstract class.
Should we implement IEquatable in a non sealed abstract class? Would it be better to implement IEqualityComparer instead?
Hey Amichai, its been a while since yor last video in these series.
waiting for domain validation and other greeate stuff
I want to ask why we don't use "!=" to check for null but instead use "is not null", what is the difference between these two ways of checking?
I am using record for ValueObjects, instead of class. What kind of difficulties I may face for it?
Am I missing some info here? Is this the final video of the series? I need to complete the app, there's a lot more to do here...
@amantinband I am wondering why not use a record for the Value Object base class. I know this video is a year old, but still was wondering what your take, or anyones take on this is?
Am I missing something here? Why wouldn't you use a record here, that would give you all the equality stuff for free. But I have to confess I haven't watched the previous videos; this one just popped up in RUclips's suggestions.
Yes and no. Check out this blog post by Vladimir Khorikov where he shows some pros and cons enterprisecraftsmanship.com/posts/csharp-records-value-objects/
How come this is part 12 but there’s only 7 vids in the playlist?
Why don't use Record for value objects?
first xD