Domain Logic Ownership
Date: 2024-01-05
Who should implement the business logic (aka send
and apply
) between Event
and State
?
trait Event {
fn apply(&self, state: &mut State);
}
// OR
trait State {
fn apply(&mut self, event: &Event);
}
When doing Dependency Injection, following Effect principles, it is preferable to use the context at the last moment so that basic elements can be built and exchanged.
// ✅ Good
struct Command {} // Can be built without knowing the context
impl Command {
fn execute(&self, context: &Context) -> (); // Also, this pattern allows us to implement variations depending on the context
}
// ❌ Bad
struct Command {
context: Context // Cannot be built without knowing the context, need to be owned and/or to have a lifetime
}
In our case, the Event
is the basic element and the State
is the context. Thus, it is preferable to use the State
at the last moment, which means that the Event
should implement apply
.
However, we also have Projection
that need to apply events and we cannot implement Vec<Event>
from the application layer.
💡
We need to implement apply
on State
and Projection
.