evolutionary-architecture / evolutionary-architecture-by-example

Navigate the complex landscape of .NET software architecture with our step-by-step, story-like guide. Unpack the interplay between modular monoliths, microservices, domain-driven design, and various architectural patterns. Go beyond the one-size-fits-all solutions and understand how to blend these approaches based on your unique needs.
MIT License
1.42k stars 171 forks source link

(Question) In Chapter 4, is there an inconsistency with raising the Contract Prepared and the Contract Signed events? #134

Closed jflaga closed 1 month ago

jflaga commented 1 month ago

In the code for Chapter 4, the ContractPreparedEvent is raised inside the Contracts entity, while the ContractSignedEvent is being raised in SignContractCommandHandler application service.

I would like to ask if it is okay to move the raising of ContractSignedEvent into the Contracts.Sign() method?

If that's not okay to do, please help me understand why not.

Are the events inside the entities different from the events in the Application layer?

Thanks.

kamilbaczek commented 1 month ago

Hey,

Good catch! Thanks for your question 😊

There are two types of events:

  1. Domain Events: Domain events are local events that should be used locally inside modules. For example, an event can be published in one concept within a subdomain and be consumed in another part of the same subdomain. Domain events are useful for making the domain explicit because they exactly match events discovered during business Event Storming sessions. These events can contain business concepts like value objects inside them. They are helpful during unit tests because we assert based on them and encapsulate properties in our domain.

  2. Integration Events: These events are external and are prepared for integration with other services. They should be stable and easy to consume. A rich domain model shouldn't leak into them, so they use simple structs.

In the example you're highlighting, we publish domain events within the domain but integration events in the application. Chapter 4 is not fully completed. The potential ultimate solution for this chapter is mapping domain events to integration events.

Here's a link to a nice video on the topic:

https://www.youtube.com/watch?v=53GsiAcKm9k&t=1s

I hope this helps! If you have any more questions, feel free to ask! 😊

meaboutsoftware commented 1 month ago

You might also hear about other naming conventions (in my opinion better ones):

jflaga commented 1 month ago

@kamilbaczek , thank you so much for the very detailed explanation.

@meaboutsoftware, thanks for that information.

Thank you also for making this project. It (together with the "Modular Monolith with DDD" project) is a good companion to the book Learning Domain-Driven Design, because that book does not have that much sample code.

Also, this project is helping me internalize the fact that a codebase does not need to have a complex architecture in the beginning, and that the architecture can evolve into a more complex one when the need arises. Before I discovered this project, and before I had read the book Learning Domain Driven Design, I had this very bad idea that codebases should at least adhere to Clean/Hexagonal architecture.

kamilbaczek commented 1 month ago

@jflaga That was exactly the idea we wanted to foster. Developers should focus on the business and environment, rather than adjusting business problems to the techniques they use.

I'm glad there are developers like you who seek knowledge and want to build better systems. If you want discuss more, please join to our discord.