| id | 0017-use-strict-cqs-across-brighter-and-darker | |||
|---|---|---|---|---|
| title | Use Strict Command Query Separation Across Brighter and Darker | |||
| status | Accepted | |||
| author |
|
|||
| created | 2024-07-24 | |||
| summary | Brighter treats all IRequest derivatives (Command, Event) as Commands in CQS terms — they mutate state and return no value; queries belong to Darker, enabling a full CQRS architecture when the two libraries are used together. | |||
| tags |
|
Date: 2024-07-24
Accepted
Command-Query Separation(CQS) states that an operation should either report state or mutate state, never both. In this way it is reliably side-effect free.
every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer. More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.
Command-Query Responsibility Segregation(CQRS) generalizes this operation principle to an architectural one where different models - a model for commands that update state, and a model for queries that read state - which often allows the query model to be optimized for reading over supporting operations.
Brighter is intended to support Commands and not Queries; Darker is intended to support Queries and not Commands.
In Brighter, we treat all derivatives of IRequest such as Command and Event are all Commands in terms of CQS. That is, they mutate state, they do not report it. (An Event has zero or more handlers, a Command has exactly one).
The lack of any return value from an IRequest occasionally causes a complication because the flow of the programme means that the caller does not know the identity of any entities created by the command.
Typically this is a problem where the identity is generated by a row being added to an RDBMS with an identity column. Whilst Darker can be used to query for the entity to get it's state, how do you query for it?
- The caller has enough information to query for the entity. This may be a natural identifier such as the name, or because the caller generates the identity, such as a ULID, over allowing an RDBMS to generate it
- A property on the
IRequestis mutable and can be set by theRequestHandlerand then inspected by the caller - The handler sets a property in the
RequestContextbag and the caller inspects that
If you want to query state, use Darker. The two libraries are intended to work together, to support CQRS.