Frequency Asked Questions
Frequency asked questions and corresponding responses are included here.
General
Why I have to use comby.AddDomainEventHandler instead of agg.AddDomainEventHandler?
The limitation is technical: in Golang, it is not possible to define generic methods for a non-generic struct. For more details, refer to https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#methods-may-not-take-additional-type-arguments.
To define aggregates with strongly-typed Domain Event Handlers and avoid boilerplate code, we utilize the helper functions provided by comby directly. This approach aims to simplify the codebase for developers.
// instead of: agg.AddDomainEventHandler
// we use: comby.AddDomainEventHandler
The comby.AddDomainEventHandler
function handles both type assertions and the registration of Domain Event Handlers within the underlying Aggregate. By leveraging this method:
- Boilerplate code is minimized.
- Code readability and maintainability are improved.
- Runtime errors due to incorrect type assertions are avoided.
For registering components relevant to the Facade, you can use the following functions:
- RegisterAggregate
- RegisterEventHandler
- RegisterCommandHandler
- RegisterQueryHandler
Within your domain, you can use the following functions to register your domain-specific handlers or to apply domain events:
- ApplyDomainEvent
- AddDomainCommandHandler
- AddDomainQueryHandler
- AddDomainEventHandler
Why is my Command serialized before it is sent to the CommandBus?
Serialization is performed upfront for pragmatic and preventive reasons. In certain situations, serialization can fail unexpectedly, especially with specific data types, leading to errors. If serialization issues were only encountered at the broker stage, it could delay problem detection and complicate debugging.
By serializing commands (and queries) early, any serialization issues can be identified and communicated promptly during development, ensuring that developers can address the problem before it reaches later stages of the system.
Additionally, the performance impact of early serialization is negligible when compared to the overhead of I/O or storage operations, making this approach a practical trade-off for better error handling and robustness.
Best Practices
What is the best way to represent a linear process?
A linear process can be effectively represented by a combination of commands and queries. Especially when instantiating new aggregates, it is useful to go through a specific process before using them. We use the term "provisioning" for this. Provisioning is essentially nothing more than a controlled sequence of commands and queries until the final result of this process is achieved. An example of this is the provisioning of a new tenant—new groups must be created, permissions distributed, etc.
To achieve this, we typically create a new domain provision
and add 1 to 2 commands and queries. We also ensure that only authorized groups have the permissions to perform the provisioning. The commands are then exposed via a REST API and can be triggered externally. Internally, the command handler can then carry out the individual steps of the provisioning, such as creating new groups, distributing permissions, etc.