Domain Modeling with Domain-Driven Design (From Scratch)

แชร์
ฝัง
  • เผยแพร่เมื่อ 9 ก.ค. 2024
  • ☄️ 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  8 หลายเดือนก่อน +3

    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 8 หลายเดือนก่อน +4

    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  8 หลายเดือนก่อน +1

      Let me make a playlist for this then!

  • @TheBadspeed
    @TheBadspeed 8 หลายเดือนก่อน +3

    Amazing video, can't wait for the next ones!

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน +3

      I've got a fun series lined up 😁

  • @alexmadnix
    @alexmadnix 8 หลายเดือนก่อน +4

    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  8 หลายเดือนก่อน +3

      Have another video on unit testing coming out soon :)

  • @sesh3219
    @sesh3219 8 หลายเดือนก่อน +1

    Thank u so much. Hyped for the modular monolith series!

  • @joehernandez3231
    @joehernandez3231 8 หลายเดือนก่อน +3

    Nicely done. Looking forward to more videos related to the activity tracker.

  • @nove1398
    @nove1398 8 หลายเดือนก่อน +1

    This is a great approach for the topic. Lots of useful information here, got a few gems from this video

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      Glad it was helpful! This will be a fun series of videos :)

  • @ibrahimhebish7744
    @ibrahimhebish7744 8 หลายเดือนก่อน +2

    You are doing a great job 👍 Milan,
    Keep it up.

  • @matheustorresdosreis9508
    @matheustorresdosreis9508 8 หลายเดือนก่อน +2

    Amazing Milan, looking forward to see how to read the values from domain events

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      Already have a few videos in the past about this, check them out

  • @julienlefevre1661
    @julienlefevre1661 4 หลายเดือนก่อน

    Very good video with practical example, clear explainations. Thanks!

  • @caseyspaulding
    @caseyspaulding 8 หลายเดือนก่อน +1

    Thanks. This was a great lesson. Keep it up.

  • @keithjairam8452
    @keithjairam8452 8 หลายเดือนก่อน +1

    Love your content…keep it up.

  • @musazulu7013
    @musazulu7013 8 หลายเดือนก่อน

    Thanks a lot @MilanJovanovicTech this is awesome can we please have the entire series related to this

  • @RiwenX
    @RiwenX 5 หลายเดือนก่อน

    This is great. Please consider creating playlists for those of us who are kinda lost

  • @adahadapato
    @adahadapato 5 หลายเดือนก่อน +1

    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

  • @ilovepandaypoe6056
    @ilovepandaypoe6056 6 หลายเดือนก่อน +1

    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.

  • @chuo129
    @chuo129 8 หลายเดือนก่อน +1

    Dear. Millan, excellent work. Have you considered make a video about multitenancy? Thanks

  • @EvekoShadow
    @EvekoShadow 2 หลายเดือนก่อน

    Would there be any downsides to using Entity and then use a strongly typed Id when extending User : Entity

  • @pavelkobjakov4148
    @pavelkobjakov4148 7 หลายเดือนก่อน +1

    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?

  • @ferventurart
    @ferventurart 8 หลายเดือนก่อน +2

    Which tool is used to do the diagrams?

  • @ZubriQue
    @ZubriQue 7 หลายเดือนก่อน +1

    I have just Models from my DB. How to know which of them are Entities, Valueo Objects or Aggregates?

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน +1

      Reading the DDD book is a good start

    • @ZubriQue
      @ZubriQue 7 หลายเดือนก่อน

      @@MilanJovanovicTech Thank you for the answer! I am half way through it as I figured out what a Value Object is at least.

  • @KrelleTG
    @KrelleTG 7 หลายเดือนก่อน +1

    Hi Milan. How would you raise a domain event for a deletion, like you have with Create?

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน

      Call a "Cancel/Delete" method on the entity and raise a domain event

    • @KrelleTG
      @KrelleTG 7 หลายเดือนก่อน

      @@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?

  • @nickst0ne
    @nickst0ne 8 หลายเดือนก่อน

    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  8 หลายเดือนก่อน

      I think you should be able to make it work with fluent config in EF Core?

  • @user-gu6pn5sv5z
    @user-gu6pn5sv5z 8 หลายเดือนก่อน

    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  8 หลายเดือนก่อน

      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: th-cam.com/video/QP0pi7xe24s/w-d-xo.html

  • @RMarjanovic
    @RMarjanovic 8 หลายเดือนก่อน

    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  8 หลายเดือนก่อน +1

      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.

  • @richardhaughton9633
    @richardhaughton9633 8 หลายเดือนก่อน

    Hi Milan. Please show us how to correctly configure DDD with EF Core. I always have trouble with private setters and constructors

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      This should help: th-cam.com/video/IlXnIe6p_Uk/w-d-xo.html

  • @peterblomqvist227
    @peterblomqvist227 8 หลายเดือนก่อน +1

    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  8 หลายเดือนก่อน

      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 8 หลายเดือนก่อน

      @@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!

  • @pooper8325
    @pooper8325 7 หลายเดือนก่อน +1

    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?

  • @Alexander-zt9kz
    @Alexander-zt9kz 26 วันที่ผ่านมา

    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 26 วันที่ผ่านมา

      Great video btw 😁

    • @MilanJovanovicTech
      @MilanJovanovicTech  26 วันที่ผ่านมา

      Module = bounded context (one way to look at it). Which translates very nicely to a microservice.

  • @pity7736
    @pity7736 8 หลายเดือนก่อน

    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  8 หลายเดือนก่อน

      It's ok to send that domain event just for instantiating the User entity

    • @pity7736
      @pity7736 8 หลายเดือนก่อน

      @@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.

  • @canodev
    @canodev 8 หลายเดือนก่อน +1

    Which tool do you use to create the diagrams?

  • @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)
    }

  • @dmytroshchotkin2939
    @dmytroshchotkin2939 7 หลายเดือนก่อน +1

    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 หลายเดือนก่อน

  • @lexuantruong3835
    @lexuantruong3835 8 หลายเดือนก่อน

    That looks like an application service rather than a domain service

  • @phennexion
    @phennexion 8 หลายเดือนก่อน +6

    Maybe im just too much of a newbie, but why all this added complexity?

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      Showcasing DDD

    • @dputra
      @dputra 8 หลายเดือนก่อน +10

      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 8 หลายเดือนก่อน

      @@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 8 หลายเดือนก่อน +1

      I gave up with youtube keep deleting my replies 😫

    • @dputra
      @dputra 8 หลายเดือนก่อน

      @@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! 😁

  • @petewarner1077
    @petewarner1077 8 หลายเดือนก่อน

    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  8 หลายเดือนก่อน

      Easily solvable with nullable reference types and some code analyzers

    • @petewarner1077
      @petewarner1077 8 หลายเดือนก่อน

      ​@@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  8 หลายเดือนก่อน +2

      @@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?

  • @enciphered7650
    @enciphered7650 8 หลายเดือนก่อน +1

    I find no utility is doing so much work. Hopefully future videos makes it clear the benefits.

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน +1

      If you don't see any value in DDD, it probably won't make sense

  • @Athurito
    @Athurito 8 หลายเดือนก่อน

    I dont like nested classes xD

  • @erandafernando94
    @erandafernando94 28 วันที่ผ่านมา

    fuck im dumb

    • @MilanJovanovicTech
      @MilanJovanovicTech  27 วันที่ผ่านมา

      Why do you say that?

    • @erandafernando94
      @erandafernando94 27 วันที่ผ่านมา

      @@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!