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

Поділитися
Вставка
  • Опубліковано 18 чер 2024
  • Spring I/O 2024 - 30-31 May, Barcelona
    Slides: speakerdeck.com/maciejwalkowi...
    Repo: github.com/maciejwalkowiak/im...
    After years of Microservices hype, it seems that our industry now understands its costs and how difficult it is to build a distributed system. We are looking again towards building monolithic applications. But how can we develop monoliths that don’t turn into an unmaintainable mess? There is no single recipe, but we can say with a high degree of confidence that domain modeling techniques presented in Domain-Driven Design, in combination with Clean/Onion/Hexagonal Architecture, can significantly help in achieving clear and well-structured code aligned with the business needs.
    In this talk, we will focus on the implementation aspects of DDD. You will understand what Aggregates, Value Objects, Repositories, Domain Events are, and how to implement them with Spring and other technologies from the Spring ecosystem. You will learn how to structure application services with Use Cases and how to leverage dependency inversion to separate technology-specific implementation details from the application and domain code.
  • Наука та технологія

КОМЕНТАРІ • 27

  • @kevindurant4952
    @kevindurant4952 10 днів тому +8

    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.

  • @msr00001
    @msr00001 10 днів тому +3

    Great example. I have continually searched for how to use Spring JPA in conjunction with DDD, however, I always felt like I was encountering too many violations. Your approach manages to keep those to a minimum so I will certainly reference this demo moving forward.

  • @roman-proshin
    @roman-proshin 10 днів тому +5

    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.

  • @TechTalksWeekly
    @TechTalksWeekly 8 днів тому

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

  • @devolajide
    @devolajide 10 днів тому +2

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

  • @MudasarRauf
    @MudasarRauf 10 днів тому +2

    very nice and informative talk

  • @ykhi
    @ykhi 10 днів тому +2

    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

  • @marceloguzman2848
    @marceloguzman2848 5 днів тому

    nice presentation, mr. homelander

  • @avalagum7957
    @avalagum7957 9 днів тому +1

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

  • @morkhoudia9
    @morkhoudia9 10 днів тому

    Great talk

  • @YZ-ix3dn
    @YZ-ix3dn 4 дні тому

    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.

  • @dimitricharles9784
    @dimitricharles9784 10 днів тому +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 10 днів тому

      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 10 днів тому

      ​@@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 10 днів тому

      @@dimitricharles9784 No. Use DTOs only when necessary

  • @abccbaandy
    @abccbaandy 6 днів тому

    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.

  • @voult89
    @voult89 9 днів тому +2

    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 8 днів тому +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 5 днів тому

      @@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 День тому

      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.

  • @nil7444
    @nil7444 10 днів тому

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

    • @anton-tkachenko
      @anton-tkachenko 19 годин тому

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

  • @SomeRandomGuyOnYT507
    @SomeRandomGuyOnYT507 7 днів тому +4

    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 19 годин тому

      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 10 годин тому

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

  • @mohammadtoficmohammad3594
    @mohammadtoficmohammad3594 10 днів тому +1

    Thank you very useful