Avoid This Common Mistake in DDD Modeling

preview_player
Показать описание

If you are applying the Domain-Driven Design, you implement entities and value objects all day. If so, you must have encountered this situation: Almost every video, article, or online resource will teach you to override Equals and GetHashCode in an entity in such a way as to proclaim two entities equal if their identities are equal.
This may be a surprise if you haven't heard it before, but that implementation is wrong. If you are guilty of it, as so many programmers are, it is the perfect time to start removing that bug from your code.
This video explains why comparing two entities for equality is impossible, let alone only comparing their IDs and ignoring other attributes.
By the time you finish watching this video, you will already start feeling better about DDD.

00:00 Intro
00:37 The wrong Entity base
03:11 Understanding the mistake
04:55 Why not Equals?
06:45 The correct Entity base
09:56 Outro

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⭐ CONNECT WITH ME 📱👨

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
👨 About Me 👨
Hi, I’m Zoran, I have more than 20 years of experience as a software developer, architect, team lead, and more. I have been programming in C# since its inception in the early 2000s. Since 2017 I have started publishing professional video courses at Pluralsight and Udemy and by this point, there are over 100 hours of the highest-quality videos you can watch on those platforms. On my YouTube channel, you can find shorter video forms focused on clarifying practical issues in coding, design, and architecture of .NET applications.❤️
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⚡️RIGHT NOTICE:
The Copyright Laws of the United States recognize a “fair use” of copyrighted content. Section 107 of the U.S. Copyright Act states: “Notwithstanding the provisions of sections 106 and 106A, the fair use of a copyrighted work, including such use by reproduction in copies or phono records or by any other means specified by that section, for purposes such as criticism, comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an infringement of copyright." This video and our youtube channel, in general, may contain certain copyrighted works that were not specifically authorized to be used by the copyright holder(s), but which we believe in good faith are protected by federal law and the Fair use doctrine for one or more of the reasons noted above.

#csharp #dotnet #domaindrivendesign
Рекомендации по теме
Комментарии
Автор

Literally 2 seconds in and you explain strongly typed Ids like it's nothing... yet that was the first lightbulb moment for me haha.

zebcode
Автор

Another excellent video highlighting a common misconception. Nice one.

fifty-plus
Автор

just another masterpiece from the maestro.

furious
Автор

Love your videos! I don't get many opportunities to implement DDD techniques as I'm still a junior working on a legacy codebase

henry-js
Автор

I have to say: Fantastic content! Thank you, sir and keep it up!

TheHegi
Автор

@4:30 — Not a book, but I have a "user" entity (keeping it simple), and a vote that the user made. So there can be a Dictionary<User, string>, where that's a lookup of the vote made by the user (though the vote is likely more complex than a string, so would have its own object). The user has identity stuff, but it would most likely have the username as the Id, not a Guid. Probably. And then you can have a HashSet<User> to contain a list of all users who voted as you process the votes.

Is the User who made a vote in post 10 the same as the user who made a vote in post 20? If you compare by user name, then yes, so you can deprecate the old vote and replace it with the new vote. The main difference, I guess, is that I'm using some content of the entity to identify it, and not some abstract guid or whatever. It would be a bit like using the book title as the ID instead of the guid (except book titles aren't guaranteed to be unique, while usernames on a forum are). Or, going the other direction, saying that the User object needed to have an ID, which would be different for the vote made in post 10 vs the one made in post 20.

But having (multiple) equality comparers built in that handle different types of comparisons is a great idea. Maybe you want to track both votes because you may need to reference either one of them as you work through the dataset, so you want to compare by username+post number when adding to the dictionary (though you only use the last post by each username when you generate the final results). So have an equality comparer for just the username (used by the HashSet), and an equality comparer for username+post (used by the Dictionary). Doesn't lend itself to an abstract base class, though.

Further, you have to be able to invert the relationship, where you have a Dictionary<Vote, List<User>>, to figure out who voted for what, which also lends itself to equality comparers on the Vote which may need to be done in multiple different ways (such as whether or not it should be case sensitive). And in this case, a guid ID for each vote that was found would be meaningless for comparison purposes.

Anyway, I think I basically agree with your point in the video, I just objected to the idea that there is no reason for those types of data structures to need some type of equality comparison. Or perhaps it's solely about having a guid as the basis for a comparison, which implicitly links it to database work. That assumption seems to carry the baggage that the ID _is_ the object, at a certain level, so if you get rid of the database association, that kind of falls away as well.

David-idjw
Автор

What About *Record* instead of Class & Service as conpare...????

drancerd
Автор

At first I didn't really like your videos because of how you talk 😅, but the content is so damn good, that I've watched them anyways and now I'm a fan.
Keep it up!

Menicoification
Автор

Hi Zoran.
Are you using the Book example together with NHibernate or EF? If so, isn't there a problematic corner case where you could compare a Book and a BookProxy in the x.GetType() == y.GetType() part of IdEqualityComparer?

AndersBaumann
Автор

I've never done anything related to equality comparison but to compare two instance of that entity type to find out, for example, what the best "score" is (if we take game scores as an example). Being equal, greater or lower should only be applied with something that make sence. Clearly, if you ever get twice the same entity within the same comparison, the issue is a bug.

Thanks for the tips on the Strongly typed ID though. I will implement that so make it more clear and avoid bugs i could cause on a friday's night lol.
I like to use uint or ulong for primary keys, since why on earth would it be negative. But for some reason EFCore migration cannot infer the type convertion (even with int). I need to do something like this:

public readonly record struct JobID(uint Id)
{
public static readonly JobID None = new(0);
}
}

p_ModelBuilder.Entity<Job>()
.Property(p_E => p_E.Id)
.HasConversion(
p_JobID => p_JobID.Id,
p_Id => new Job.JobID(p_Id));

Any idea why? Since you never mentionned it in your past video, i thought there was never the need to do this.

WDGKuurama
Автор

It’s fascinating to think about how entity equality can actually undermine the core principles of Domain-Driven Design. What do you think about applying an immutable approach to entities to avoid these pitfalls altogether?

OscarAgreda
Автор

You need to override equals when syncing records form one database to another to check if source records need to be updated in the target database.

sheeeeep
Автор

I would create those Dictionary and hashset to make my colleges to drive crazy, and either to make their hair gray or loose then all 🙂 Like 10 years ago I run into this problem, I was debugging a mathematician's guy code 🙂 They could not fix in in 2 months 😀

zbaktube
Автор

DDD is such a confusing topic. And Eric's book is fundamental, but a book which one has to read at least three times to get a grip of. Great video though, at least this one I understand clearly :) Could you recommend any good Udemy DDD course by any chance? Can't find the one you recommended there and Pluralsight is not an option for me :(

dennym
Автор

Zoran I just wanted to comment to say that I find your videos very useful and it would be great if you added a Patreon tier for "just saying thanks" for £2/month where you don't get anything additional, but want to show your appreciation anyway :)

dave_s_vids
Автор

only thing i got from this video, some codes are useless until you know the use at given point of time.

aamirali
Автор

You might want to store entities in collections that are read optimized, no?

pyce.
Автор

Hey Zoran, Would like to exchange an idea.
What about entities that are the same and have multiple registration by software design. For example: In the Family Tree web site, different users can register the same person: I and my distant relatives have register our great-great-grandmother in the site, so there is lots of Entities that are indeed the same. The website recognizes it and suggest a merge.
Great Content!

wiliam.buzatto
join shbcf.ru