Implementing Domain Driven Design with Spring by Maciej Walkowiak @ Spring I/O 2024

Поделиться
HTML-код
  • Опубликовано: 22 дек 2024

Комментарии • 81

  • @kevindurant4952
    @kevindurant4952 6 месяцев назад +36

    00:00 - 04:22 Introduction
    04:23 - 04:58 What is DDD?
    04:58 - 06:08 What does DDD mean for developers: Understanding the domain.
    06:08 - 06:32 What does DDD mean for developers: Split big domains into subdomains.
    06:32 - 08:00 What does DDD mean for developers: Develop an ubiquitus languages.
    08:00 - 08:35 What does DDD mean for developers: Develop a domain model + separate domain model from implementation details.
    08:35 - 09:24 The Old Testament and the New Testament.
    09:28 - 13:20 What is the domain model: introduction.
    13:40 - 16:23 Existing Library Software: anemic domain anti-pattern.
    16:24 - 17:14 Why we don't want this approach.
    17:24 - 20:02 DDD Library: User Stories and what they tell us.
    20:02 - 20:42 DDD Library: Implementation start.
    20:42 - 25:20 DDD Library: Creating the domain model.
    25:20 - 26:40 DDD Library: JPA vs separate domain models.
    26:40 - 30:15 DDD Library: adapting domain model to work with JPA (@Embedded and @EmbeddedId).
    30:15 - 33:27 DDD Library: Creating the Copy class and a note on @ManyToOne in DDD (31:24).
    33:27 - 37:00 DDD Library: implementing the use-cases, the wrong way.
    37:00 - 39:53 DDD Library: implementing the use-cases, the correct way using dependency inversion.
    39:53 - 41:30 DDD Library: Service Taxonomy using custom Java @Annotations.
    41:30 - 45:07 DDD Library: Bounded Context #2 Lending books.
    45:08 - 46:03 Enforcing module separation using Modulith tests.
    46:04 - 48:50 What if some modules need to depend on eachother? Solution: extend AbstractAggregateRoot and work event driven.
    48:51 - 50:17 Outro.

    • @rapoliit
      @rapoliit 2 месяца назад

      I say Really thank you.

  • @nikolairomanov6054
    @nikolairomanov6054 4 месяца назад +28

    I find it kidna funny that we say that "classical layered approach" can work for small projects and then we try to show benefits of DDD on the same small examples.
    But sometimes (quite often) in big systems we choose verbosity to provide better clarity and reduce coupling.
    To me it was terrifying what happened to our domain by the end of the presentation.

    • @painnagato7617
      @painnagato7617 21 день назад

      I liked the comment, could you explain your point better?

  • @ykhi
    @ykhi 6 месяцев назад +11

    I think what we usually did was to create a BookEntity class in the infra layer and together with Mapper classes(that maps domain object to corresponding database entity object), this way we separate the domain object definitions from the database variations of it according to the onion architecture's separation of concerns

  • @devolajide
    @devolajide 6 месяцев назад +3

    Finally, I have been waiting for the video to be uploaded.

  • @TechTalksWeekly
    @TechTalksWeekly 6 месяцев назад +4

    This talks is excellent and it has been featured in the last issue of Tech Talks Weekly newsletter 🎉
    Congrats Maciej!

  • @Alx-gj2uz
    @Alx-gj2uz 4 месяца назад +1

    I found the idea of coding the implementation as userstories / usecases extremely insightfull, seeems to work really well with ddd. Goes hand in hand with good architecture documentation and requirements engineering and is pretty good from a perspective as "code as documentation". Never thought of this.
    Its roughly at timecode 34:30

  • @aditya789101
    @aditya789101 5 месяцев назад

    Clear and detailed. Thank you for the efforts!

  • @GeorgeBentes
    @GeorgeBentes 7 дней назад

    I got confused when he added some JPA annotations to the domain classes. I thought they should be agnostic to any framework. In this case, did he break any DDD rule?

  • @gokhanuysal_dev
    @gokhanuysal_dev 6 дней назад

    Is it really okay to put repository interface inside the domain object? Isn't the domain service is for? I am new to ddd so sorry for my poor knowledge.

  • @roman-proshin
    @roman-proshin 6 месяцев назад +7

    The code will look much better once we replace JPA with Spring Data: it supports immutable entity classes out of the box, it kinda forces identifying aggregates.

    • @painnagato7617
      @painnagato7617 21 день назад

      I was interested, could you tell me more about it?

  • @YZ-ix3dn
    @YZ-ix3dn 6 месяцев назад +19

    I feel this approach a bit confusing especially when you pass repository into the domain entity. What can be more straightforward than having 3 main layers (Controller, Services, Repositories). In real life scenarios, there might be a lot of communication with different systems, so putting all that logic in service layer looks more reasonable for me. And basically these UseCase classes could be in fact small granular services e.g. AddBookToCatalogService.

    • @atrucktive
      @atrucktive 4 месяца назад

      That’s just upgrading the old MVC to MCV 2.0 (with Trushtero services)
      With this approach you are going to really take care of the business domain and clean architecture

  • @MudasarRauf
    @MudasarRauf 6 месяцев назад +2

    very nice and informative talk

  • @pentasung
    @pentasung 5 месяцев назад +1

    Why is Book an entity and not a VO in the catalog domain ?

  • @ederortega9606
    @ederortega9606 Месяц назад

    what is the difference betwen service and use case

  • @ralte89
    @ralte89 2 месяца назад

    Thanks for this talk, very informative.
    For creating an audit trail of a user, would events, or Aspect be prefered ? It seems that with spring modulith we can achieve the same result of using Aspect. If we use events we can even have a module audit, and have the audit persistence and reading of such decoupled

  • @AlexanderBondarenko-w9f
    @AlexanderBondarenko-w9f 5 месяцев назад

    Thanks for the presentation! Is a repository of non-DDD example of library available somewhere?

  • @julianruppel9171
    @julianruppel9171 5 месяцев назад

    Perfect talk, enjoyed it a lot

  • @atrucktive
    @atrucktive 4 месяца назад +5

    25:27 DDD code review.
    - You don’t need to RE-validate the ISBN value object.
    - Domain coupled to infrastructure (framework)

    • @williamsbotchway2471
      @williamsbotchway2471 2 месяца назад +2

      - Domain coupled to infrastructure (framework). This is bullshit. Java got to fix this and have a better way to deal with this.

    • @painnagato7617
      @painnagato7617 21 день назад

      @@williamsbotchway2471 watching the talk I had the same feeling, we are suffering because Java has a rigid way of dealing with object-to-data mappings, someone needs to do something

  • @hackstreet781
    @hackstreet781 2 месяца назад +1

    After watching this video, it feels like my 7 years of experience was a lie. It is so tough to implement by ourselves.

  • @aurevoir641
    @aurevoir641 3 месяца назад +7

    normal people at 5 am: sleeps
    devs at 5 am: watches this video

    • @nmprecious
      @nmprecious Месяц назад

      I just woke up at 5:00am to watch this. It's 5:08am now.

  • @dimitricharles9784
    @dimitricharles9784 6 месяцев назад +2

    Nice talk. Just one question, in the BookSearchService takes an Isbn as parameter, but the Isbn type is defined in domain layer but used in the app and infrastructure layer. Would passing a String representation of a isbn sufficient ?

    • @roman-proshin
      @roman-proshin 6 месяцев назад +2

      It’s absolutely fine as any of these “layers”/“modules” can use domain classes. That’s the whole purpose of the design: keep the domain module pure and clean, and have all the rest of the application to use that domain to actually get a working application.

    • @dimitricharles9784
      @dimitricharles9784 6 месяцев назад

      ​@@roman-proshin Oh ok I have never thought of it that way. So there is no mapping to a DTO needed when returning an entity from the domain to a Restful request ?

    • @diego.schmidt
      @diego.schmidt 6 месяцев назад

      @@dimitricharles9784 No. Use DTOs only when necessary

  • @MateuszNaKodach
    @MateuszNaKodach 4 месяца назад +1

    The repository call in the domain object even does not guarantee the rule is not broken, because it's not transactional consistent...
    I think no-one should do something like that. There is a lack of some Availability concept in the domain.

  • @marceloguzman2848
    @marceloguzman2848 6 месяцев назад +1

    nice presentation, mr. homelander

  • @Beny_gx
    @Beny_gx 3 месяца назад +1

    If one uses jpa entity classes that need mapping to domain objects there will be quite so code gymnastics to lazy load collections because mapping them will always result in an eager fetch

  • @ogyct
    @ogyct 5 месяцев назад +2

    Can't say I liked it. In the very beginning we say, that our domain should be framework agnostic and yet we introduce jpa entities right into it.
    Next we implement BookSearchService in infrastructure. Oh wait, let's just put it in application package just because that's the rule. What is the difference between infrastructure and application then?
    When creating Loan domain, we introduce LoanRepository argument into its constructor. Why?
    And there's much more I don't get about it. In the end, even if somehow manage to understand it, how am I supposed to explain it to the others.

    • @guybrushthreepwood2910
      @guybrushthreepwood2910 6 дней назад

      I'm too late, but I'll share my thoughts:
      1) Regarding JPA and domain: you are right. He did really mixed those two. But he was just trying to show that sometimes you can opt for pragmatism, taking into consideration that JPA annotations nowadays are quite evolved and they are not so intrusive. However, you can still separate it if you are willing to pay the price that he also showed.
      2) Regarding BookSearchService: the important point here is the introduction of IsbnSearchService (the interface). It looks subtle, but the implication is quite significant. This interface is owned by the application. The application says "if you want to plug infrastructure into my logic, you have to conform to this interface". It's an interface that is minimal and thought specifically for that purpose. This means that now your business logic is decoupled from the infrastructure. You will then "plug" the infra implementation (BookSearchService) into that interface (port).
      3) Regarding LoanRepository inside Loan class, I've never done that. I personally dislike it, or I will say that I'm not convinced that it's a good idea because this could also lead to other methods in that class to depend on other repo methods. I prefer for my domain classes to be unaware of ports/interfaces. It seems to violate the dependency direction rule in Hexagonal Architecture. Domain should not depend on the application services, but the other way round.

  • @avwie132
    @avwie132 2 месяца назад +2

    Mixing domain and framework. Nice

  • @mrowox
    @mrowox 5 месяцев назад

    Can DDD be employed to develop any type of software of is this peculiar to certain type of softwares?

    • @AntonioDoesMetal
      @AntonioDoesMetal 5 месяцев назад +3

      Just my 2 cents DDD is a design pattern specifically for somewhat complex to complex business domains. If you're doing scripting or building small apps that don't have tons of complex business logic and entities than best to stick with what you know. However if you're working with a complex business domains DDD really shines and shows you how badly you've been building software lol. Like imagine a freight shipping company that deals with delivers packages internationally. There are tons of different laws you may have to deal with from different countries in a single trip. Between that and varying currencies, delays, timezones etc you could imagine there's tons and tons of "tribal knowledge" that the business users know about how it all works that's probably not really documented anywhere. So when building software for those people to solve a problem they have, it's important that you model your software correctly so it doesn't implode as things change and code needs to be modified/extended. Writing the code is almost secondary, design and understanding your users domain space is primary. Hope this helps

    • @AJewFR0
      @AJewFR0 3 месяца назад +1

      Implementing DDD chapter 1 has some guidance on answering this question. If you start talking to a domain expert to try to understand the problem and you keep finding caveats (i get concerned after 3-5 branches down a certain process pipeline), it is time to go back and apply DDD more formally. But you should consult the book for a more holistic answer because every domain is different. But if it is complex to you and your customer, it is probably complex.

  • @cariyaputta
    @cariyaputta 5 месяцев назад

    Nice talk. Thanks.

  • @FiruzzZ-777
    @FiruzzZ-777 3 месяца назад

    so all the control/validation/restrictions/events will be in an Entity/POJO, services and business layers are empty :/ ... you manage the entire flow of a project by the actions performed against "the domain"

  • @ZapOKill
    @ZapOKill 4 месяца назад

    I thought that the combination of @Entity and @Data is discouraged.

  • @morkhoudia9
    @morkhoudia9 6 месяцев назад

    Great talk

  • @williamsbotchway2471
    @williamsbotchway2471 2 месяца назад +3

    The issue with keeping the data model and the domain model together is a problem with java and spring. C# with dotnet solves the problem in an much elegant way. This makes C# a go to framework when we talk about DDD. U should alway keep your domain model free from any infastructure concerns. Unfortunately spring jpa makes such aproach look like a boilerplate. This is a violation of the single responsibility principles?

  • @haroldpepete
    @haroldpepete Месяц назад

    ummm i've read in a lot of places about how bad is uuid like a id in database, it aint sortable and the index may be messy

  • @nil7444
    @nil7444 6 месяцев назад +1

    the repository call in the domain object is weird, just build a specification class and pass that instead.

    • @anton-tkachenko
      @anton-tkachenko 5 месяцев назад

      Yeah, that's weird, especially when you need to create / update 10 000 entities...

  • @isbey9595
    @isbey9595 3 месяца назад

    There is something codesmell I think. Domain layer should be written as pure as possible. Repository definition and entity definitions violate something here.Tests of the domain layer should also be written independently. But there is JPA dependency here.

  • @scerrisebastien
    @scerrisebastien 3 месяца назад

    Interesting but Domain driven design I still don't get the benefits on micro services at least. A lot of classes and complexity. Yes small classes are simpler to maintain.
    Anyway I will continue the journey with the videos you mentioned.

  • @avalagum7957
    @avalagum7957 6 месяцев назад +6

    record BookId(UUID)
    record ISBN(String)
    ....
    These wrappers create more tasks for the GC. I'm waiting for the day when the Java compiler supports new type/opaque type like the Scala compiler (i.e. we still have BookId and ISBN but the compiler will remove them while still keeping all the validations inside them).

    • @nikolairomanov6054
      @nikolairomanov6054 4 месяца назад +5

      If you start to carry about java GC optimisations like this, you probably need to get rid of all "spring-data" and lots of other stuff first.

  • @voult89
    @voult89 6 месяцев назад +5

    In my opinion, the domain shouldn't know anything about how the entity will be saved, updated or whatever, and where it would happen.
    For the domain it should be an abstraction.
    For example, you can decide not to use JPA, and use JDBC instead. And if you're designed your application correctly, you won't change anything in domain module, you won't even recompile it, and only persistence module will be changed.
    And modulith only help you design you monolith application, not microservice with DDD. But gradle can, since for each module (presentation, persistence, use cases, domain) you can set it's own dependencies. And, for example, domain will never depend on use cases, and you can even write tests for that. And you don't even need to recompile inner modules, when you change anything in outer modules.

    • @rolandjost3823
      @rolandjost3823 6 месяцев назад +1

      Indeed, your vision or your approach is correct. In addition, I noticed that there are two architectural approaches to doing DDD. Obviously the one you described above, and the one he presents in his talk based on Spring Data JDBC (AggregateRoot) using JPA annotations.
      Your approach is ideal since it avoids a decoupling between the business domain and the infrastructure layer, however it requires a lot of DTO.
      In short, note that the DDD approach is a free approach, since it is based on a set of good practices (TDD, BDD, CLEAN ARCHI and others). But does not define any specific architecture.
      Personally I recommend using the one that will allow you to deliver your software faster

    • @FernandoDBozzo
      @FernandoDBozzo 6 месяцев назад

      @@rolandjost3823
      Fast Delivery in this way normally implies slowing maintenance in the future. I don't know if everything is valid just for Fast Delivery...

    • @MrVitalirapalis
      @MrVitalirapalis 5 месяцев назад

      I agree with you @voult89, how would you structure your microservice ddd project? Can you provide some example. Just module, package names and so on.

    • @Boss-gr4jw
      @Boss-gr4jw 5 месяцев назад +1

      If you have an interface which exposes save function and it is implemented in infrastructure layer, then the domain will never know how something is persisted or which is the underlying technology, this is exactly what was demonstrated here.

    • @voult89
      @voult89 5 месяцев назад

      @@Boss-gr4jw Nope. He used annotation "Entity" and to use it as a JPA entity he made domain "Entity" mutable, created no arg constructor for JPA and so on. So, your domain module already knows what technology will be used.
      data-JDBC, for example, doesn't need any of this staff.

  • @abccbaandy
    @abccbaandy 6 месяцев назад +1

    Great talk, but still don't see any chance to use this in real world biz logic.
    For example:
    It do valid in domain object, but what if I got a new requirement that I need bypass or add some valid in some biz logic? It seems hard to do this new task.
    Instead, with old school POJO way, it's easy.

  • @AbdelrhmanHussien-sx8vb
    @AbdelrhmanHussien-sx8vb 3 месяца назад

    I feel like if I found a treasure

  • @kevinmaltby4202
    @kevinmaltby4202 Месяц назад

    Another year, another 'shiny concept'. Seems like this one is going to take us back to monoliths with the addition of confusion of what 'domain driven design' is. Seems like its someone else's turn in the spotlight to sell books and courses. I note hardly anyone talks about having a multi-module spring project e.g. multi-module Maven to decompose an application into. A lot less confusing than trying to introduce yet another concept/buzz-phrase/buzz-idea.

  • @king20031
    @king20031 2 месяца назад

    axon is the best ddd framework in java word

  • @SomeRandomGuyOnYT507
    @SomeRandomGuyOnYT507 6 месяцев назад +8

    This might looks fancy but In my work experience, this way of modeling microservice is worst thing you can do in fast developing world. I want my developers to get features out as fast as possible with proper testing. I don't want them to waste time in managing packages.
    controller, service, entities, repositories, util, helper. with No shitty one interface, one class thing.
    just keep it simple !! You are not gonna need it.

    • @anton-tkachenko
      @anton-tkachenko 5 месяцев назад

      One interface is good. You have a list of use cases in one place. I think they used to call it a facade :)
      If needed, implementation can be split into classes

    • @SomeRandomGuyOnYT507
      @SomeRandomGuyOnYT507 5 месяцев назад

      @@anton-tkachenko when needed your IDE can refactor out an interface in just 2 clicks. 🫠

    • @Boss-gr4jw
      @Boss-gr4jw 5 месяцев назад +2

      That's how you end up with the anemic model and god classes which are impossible or hard to test. Also you end up putting functions together into services which are not related at all. This all results in so fragile code, hard to change, every change requires full recompilation of unrelated classes, slow builds, slow tests etc. There is a reason for why you should be designing into interfaces and smaller classes and packages. For very small service there is no reason not to put everything into same package, if it really is small.

    • @phamnguyen3083
      @phamnguyen3083 5 месяцев назад +2

      I know many people love this approach because they never write a single test, so one big class works for them.

    • @puraverdad2022
      @puraverdad2022 4 месяца назад +5

      this approach intend isn't for simple projects or APIs (for that u can still use plain MVC), when a project grows and this involves scaling in complexity, let say after 1.5 year aprox, when more business rules are added if you don't have a Clean Architecture then u'll find out that the code is a mess and highly coupled, then making adaptations among business rules look really dirty in legacy approaches. Making code as faster as possible is the opposite of making high quality code (I prefer having code well organized and tested that can adapt in the future easily than writting fast code for a user story than will be broken in the near future)

  • @Anshulkatta
    @Anshulkatta 16 дней назад

    This will eventually cause more confusion,

  • @mohammadtoficmohammad3594
    @mohammadtoficmohammad3594 6 месяцев назад +1

    Thank you very useful