Domain Modeling with Domain-Driven Design (From Scratch)

  Рет қаралды 22,862

Milan Jovanović

Milan Jovanović

Күн бұрын

☄️ Master the Modular Monolith Architecture: bit.ly/3SXlzSt
📌 Accelerate your Clean Architecture skills: bit.ly/3PupkOJ
🚀 Support me on Patreon to access the source code: / milanjovanovic
Domain-Driven Design is a set of principles for how you can design and model a rich domain in your application. In this video, I'll do a domain modeling exercise from scratch. I'll start with a diagram of a domain model and then I'm going to apply some Domain-Driven Design patterns to create the domain models.
Join my weekly .NET newsletter:
www.milanjovanovic.tech
Read my Blog here:
www.milanjovanovic.tech/blog
Chapters
0:00 What we are building
1:09 Creating the first Entity
2:36 Value Objects - why they are useful
5:00 Defining an Entity base class
6:07 Using the Static Factory pattern
7:33 Decoupling side effects using Domain Events
10:13 Writing unit tests for the Name value object
13:48 Implementing custom guard clauses
16:02 Writing unit tests for the User entity

Пікірлер: 94
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Each week, I send one piece of practical advice about .NET and software architecture. It's a 5-minute read (or less) and comes every Saturday morning. 📌 Join 30,000+ engineers → milanjovanovic.tech
@akeemaweda1716
@akeemaweda1716 7 ай бұрын
Hi Milan, glad you posted this. Have added something new to my knowledge base. Will ensure I follow through the series. Hope it's going to be in its own playlist 😊 Thanks a million.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Let me make a playlist for this then!
@alexmadnix
@alexmadnix 7 ай бұрын
Thank you. Milan I've been using C# for a long time, but I've rarely utilized unit testing, so it's something I'm still pretty low on, but after taking the course, I've gained a lot of confidence in it.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Have another video on unit testing coming out soon :)
@TheBadspeed
@TheBadspeed 7 ай бұрын
Amazing video, can't wait for the next ones!
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
I've got a fun series lined up 😁
@joehernandez3231
@joehernandez3231 7 ай бұрын
Nicely done. Looking forward to more videos related to the activity tracker.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Coming soon!
@sesh3219
@sesh3219 7 ай бұрын
Thank u so much. Hyped for the modular monolith series!
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Hope you enjoy it!
@matheustorresdosreis9508
@matheustorresdosreis9508 7 ай бұрын
Amazing Milan, looking forward to see how to read the values from domain events
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Already have a few videos in the past about this, check them out
@julienlefevre1661
@julienlefevre1661 3 ай бұрын
Very good video with practical example, clear explainations. Thanks!
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Glad it was helpful!
@ibrahimhebish7744
@ibrahimhebish7744 7 ай бұрын
You are doing a great job 👍 Milan, Keep it up.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Appreciate it! :)
@nove1398
@nove1398 7 ай бұрын
This is a great approach for the topic. Lots of useful information here, got a few gems from this video
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Glad it was helpful! This will be a fun series of videos :)
@caseyspaulding
@caseyspaulding 7 ай бұрын
Thanks. This was a great lesson. Keep it up.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Glad you liked it!
@keithjairam8452
@keithjairam8452 7 ай бұрын
Love your content…keep it up.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Glad you enjoy it!
@RiwenX
@RiwenX 5 ай бұрын
This is great. Please consider creating playlists for those of us who are kinda lost
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
Good suggestion 😅
@musazulu7013
@musazulu7013 7 ай бұрын
Thanks a lot @MilanJovanovicTech this is awesome can we please have the entire series related to this
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Working on it!
@chuo129
@chuo129 7 ай бұрын
Dear. Millan, excellent work. Have you considered make a video about multitenancy? Thanks
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Yes, soon
@peterblomqvist227
@peterblomqvist227 7 ай бұрын
Thank you for once again a very good and pedagogic video. I like them all. I have a different situation. We have an old, quite large, database. And I want to refactor the systems around it. My approach is to add a database model (classes reflecting the database who are created by scaffolding), in the infrastructure project together with mappings to and from the new domain model I want to build. I know that it's not optimal adding another DTO layer which also adds complexity. But I don't know what else I could do. A mapping from the database (with Fluent API) to the domain model will be quite complicated (because the db model and the domain model will be so different) and I'm not sure if it's possible to do. Do you have an opinion how to implement a (DDD) domain model for an existing database or another approach to my problem? I must also mention that the primary keys are not GUIDs, they are integers and many times identity columns.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Your approach is fine. The cost is added complexity and more code to maintain. But as long as you have a clear mapping from DB model to Domain model (and vice-versa) - you're on the right track.
@peterblomqvist227
@peterblomqvist227 7 ай бұрын
@@MilanJovanovicTech 👍Thank you Milan. That was good to hear from an external person 😊 I'm trying to use Mapperly for the mapping part. But it's hard to use with value objects. I can't get it to work... I haven't seen any video or found any webpage explaining how that is done. I'll continue checking your great videos and get good ideas from you. Thanks again for the job your doing!
@adahadapato
@adahadapato 5 ай бұрын
thank you for putting this together, please how do I use this Entity base class with entities that have keys named differently from Id. say Code, etc
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
You can configure that with EF
@ferventurart
@ferventurart 7 ай бұрын
Which tool is used to do the diagrams?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Excalidraw
@pooper8325
@pooper8325 7 ай бұрын
Hi Milan, I really like this video. Can you also do a video when an aggregate user owns an entity and in the infrastructure layer identityuser is used to handle authentication/authorization?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Planning to do it :)
@user-gu6pn5sv5z
@user-gu6pn5sv5z 7 ай бұрын
Great video, Milan, does You consider making video about how to deploy app into production? This would be great supplementation of your Clean Architecture course. Without any doubt, i would like to see how You deploy your built on docker app into production using for ex. Azure.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
That's an awesome suggestion! I have a CI video coming out soon, but I'll work on a deployment one afterwards. In the meantime, there's this: kzbin.info/www/bejne/h4GToZxtrcplatU
@EvekoShadow
@EvekoShadow Ай бұрын
Would there be any downsides to using Entity and then use a strongly typed Id when extending User : Entity
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
Other than the complexity?
@richardhaughton9633
@richardhaughton9633 7 ай бұрын
Hi Milan. Please show us how to correctly configure DDD with EF Core. I always have trouble with private setters and constructors
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
This should help: kzbin.info/www/bejne/f527n3yba9WSi80
@nickst0ne
@nickst0ne 7 ай бұрын
I love the strongly-typed properties like the user's name in this video. But I have difficulty setting up the persistence of entities for such properties. I know I've seen it done in one of your videos but it requires a full control on the context, which is something I didn't have in one project where it was database-first and the scaffolding was configuring the context. I think the persistence of strongly-typed ids/properties would deserve a video of its own, considering the different ORMs or approaches.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
I think you should be able to make it work with fluent config in EF Core?
@RMarjanovic
@RMarjanovic 7 ай бұрын
What are your thoughts on passing primitive types in the static factory methods instead of Value Object types? I find that I'm cluttering and needing to check lots of results in my use cases before I can actually create the entity / aggregate root. Instead I move the logic of creating value objects to the entity and can combine the results using your railway oriented implementation.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
I like to assume that everything has been checked by the time I hit my domain entities. But I'm totally not against your approach. I can see how it simplifies the use cases, and moves more of the responsibility to the domain.
@RMarjanovic
@RMarjanovic 6 ай бұрын
@@MilanJovanovicTech After using this for a while and testing with a profiler I noticed that for my usecases I recreate the strongly type id value objects a lot by using this approach. Which caused some performance hits. I refactored to use your approach instead.
@pity7736
@pity7736 7 ай бұрын
Nice video. Thank you! I have a question: is ok to send that domain event just for instantiating the User entity? What should be the case when User entity is creating a object just because a query from UserRepository? You're not creating a User itself, just instantiating the entity. Thanks!
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
It's ok to send that domain event just for instantiating the User entity
@pity7736
@pity7736 7 ай бұрын
@@MilanJovanovicTech But every time? Imagine that you need to send a welcome email to the user when is created in the system. In that case is perfect. But, imagine that you query that user from database to make login, for example, that domain event will be raised too and the welcome email will be sent. In this case is not so good.
@KrelleTG
@KrelleTG 6 ай бұрын
Hi Milan. How would you raise a domain event for a deletion, like you have with Create?
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Call a "Cancel/Delete" method on the entity and raise a domain event
@KrelleTG
@KrelleTG 6 ай бұрын
@@MilanJovanovicTech But when would you do this? In this case you call it on example.Create(), but you do not necessarirly have a domain entity in delete. Would you call it in a service layer?
@Alexander-zt9kz
@Alexander-zt9kz 6 күн бұрын
I am new to DDD, modular monoliths, and designing microservices. Are the modules in your monolith the same as what should be it's own microservice? IE, we have an excercise and a workout module, so would we have an excercise and workout microservice if we were to use microservices?
@Alexander-zt9kz
@Alexander-zt9kz 6 күн бұрын
Great video btw 😁
@MilanJovanovicTech
@MilanJovanovicTech 6 күн бұрын
Module = bounded context (one way to look at it). Which translates very nicely to a microservice.
@ilovepandaypoe6056
@ilovepandaypoe6056 6 ай бұрын
What is the advantage of using an abstract instead of interface for the entity class?
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
The lines are blurred because you can also define default implementations in interfaces. But abstract classes can have internal state.
@canodev
@canodev 7 ай бұрын
Which tool do you use to create the diagrams?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Excalidraw
@ZubriQue
@ZubriQue 6 ай бұрын
I have just Models from my DB. How to know which of them are Entities, Valueo Objects or Aggregates?
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Reading the DDD book is a good start
@ZubriQue
@ZubriQue 6 ай бұрын
@@MilanJovanovicTech Thank you for the answer! I am half way through it as I figured out what a Value Object is at least.
@pavelkobjakov4148
@pavelkobjakov4148 7 ай бұрын
Why in Name record we are use nullable type in constructor? If I want to create an instance of the Name record then i'll expect that i can pass NULL to Name record, because it accept a nullable type and VS studio don't show me, that i wrong, because constructor accept nullable string but in runtime i get exception
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Compile-time and runtime constraints behave differently
@pavelkobjakov4148
@pavelkobjakov4148 7 ай бұрын
@@MilanJovanovicTech do I understand correctly that in this way we lose the possibility of hints from the IDE and get an error (warning) not at the compilation stage, but in runtime? What is the advantage of this approach?
@fiqrihafzain2820
@fiqrihafzain2820 6 ай бұрын
can domain modeling to do something like this in clean architecture? data class DevByteVideo(val title: String, val description: String, val url: String, val updated: String, val thumbnail: String) { val shortDescription: String get() = description.smartTruncate(200) }
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Why not?
@dmytroshchotkin2939
@dmytroshchotkin2939 7 ай бұрын
4:11 I don't get it. You've created a public ctor in which you're accepting a nullable string argument BUT you're immediately throwing an exception if a 'null' is passed. Why did you make the argument nullable then? You need to do it ONLY if 'null' IS a valid value for the parameter. Otherwise you should explicitly declare that you expect non-null value and to throw an exception if you get 'null'.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Just a guard clause example, gets cleaned up later
@techpc5453
@techpc5453 7 ай бұрын
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
👋
@lexuantruong3835
@lexuantruong3835 7 ай бұрын
That looks like an application service rather than a domain service
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Why?
@phennexion
@phennexion 7 ай бұрын
Maybe im just too much of a newbie, but why all this added complexity?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Showcasing DDD
@dputra
@dputra 7 ай бұрын
The point of ddd is in the effort to align software development (technical) with your users' business cases (domain). You are building a bridge between the developers and the users, creating better communication and collaboration. The first step to achieve this is to identify the "domain" of your user business. What is the entities that will be in the business? What can you do with them? It's necessary to use the proper term, according to your users, of your entity classes. Because keeping the domain knowledge is important in DDD, we have to build a whole structure of projects that builds around those entities. DDD shines if you have expert users and many developers with knowledge gap between them.
@phennexion
@phennexion 7 ай бұрын
@@dputra interesting, thanks for that reply. So I'm guessing it's really good for when a company outsources it's development and helps the developers understand what they're trying to do better?
@dputra
@dputra 7 ай бұрын
I gave up with youtube keep deleting my replies 😫
@dputra
@dputra 7 ай бұрын
@@phennexion It's even impossible for the internal IT team to know exactly the business needs. Softwaremill wrote a good article about DDD. Just google it! 😁
@enciphered7650
@enciphered7650 7 ай бұрын
I find no utility is doing so much work. Hopefully future videos makes it clear the benefits.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
If you don't see any value in DDD, it probably won't make sense
@petewarner1077
@petewarner1077 7 ай бұрын
It is not true when you say "Name cannot be null" for the static factory method on User just because the parameter type is not marked as nullable. The consumer can explicitly call User.Create(null), ignoring any warnings and the intent of the method. This is exactly the scenario where you *do* want a guard clause. Conversely, the nullability of the value parameter of the Name record should *not* be nullable since you have a guard that will throw if the consumer does pass null.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Easily solvable with nullable reference types and some code analyzers
@petewarner1077
@petewarner1077 7 ай бұрын
​@@MilanJovanovicTech Sorry Milan, I didn't understand your reply. Trying to clarify my own comment: In your video, you have a nullable reference type, and guard against it being null. You also have a non-nullable reference type but don't guard against that being null. You state that the Name value passed to the factory method cannot be null - it can. It's not a struct.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
@@petewarner1077 Conceptually, yes - it can be null. But in any normal execution flow it will never be null. And I'm saying you can guard against this with nullable reference types + code analyzers. You can turn "treat warnings as errors" and the build will never pass if you're trying to pass null for a non-nullable value. Does that make sense?
@Athurito
@Athurito 7 ай бұрын
I dont like nested classes xD
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Easy to clean up 😁
@erandafernando94
@erandafernando94 9 күн бұрын
fuck im dumb
@MilanJovanovicTech
@MilanJovanovicTech 8 күн бұрын
Why do you say that?
@erandafernando94
@erandafernando94 8 күн бұрын
@@MilanJovanovicTech quite hard to catch up lol. had to watch few times. but keep them coming! if u can dumb it down a bit, that would great!
How To Use Domain-Driven Design In Clean Architecture
30:27
Milan Jovanović
Рет қаралды 101 М.
2000000❤️⚽️#shorts #thankyou
00:20
あしざるFC
Рет қаралды 16 МЛН
Пробую самое сладкое вещество во Вселенной
00:41
Essence of Domain-Driven Design (DDD)
27:09
CodeOpinion
Рет қаралды 17 М.
Clean Architecture Project Setup From Scratch With .NET 7
12:02
Milan Jovanović
Рет қаралды 114 М.
How To Implement Domain-Driven Design (DDD) in Go
1:57:42
ProgrammingPercy
Рет қаралды 36 М.
Domain-Driven Refactoring - Jimmy Bogard - NDC London 2022
1:00:03
NDC Conferences
Рет қаралды 43 М.
Domain Driven Design Part1 with Hassan Ibrahim - بالعربي
1:17:21
Software ArchTalks for Arabs
Рет қаралды 6 М.
DDD By Example - Paul Rayner - DDD Europe 2020
54:58
Domain-Driven Design Europe
Рет қаралды 48 М.
Купил этот ваш VR.
37:21
Ремонтяш
Рет қаралды 265 М.
How charged your battery?
0:14
V.A. show / Магика
Рет қаралды 6 МЛН
Мечта Каждого Геймера
0:59
ЖЕЛЕЗНЫЙ КОРОЛЬ
Рет қаралды 1,6 МЛН
Gizli Apple Watch Özelliği😱
0:14
Safak Novruz
Рет қаралды 2,4 МЛН