@@ -5,10 +5,19 @@ date: 2022-07-15
55tags : [server]
66---
77
8- # 0008 - Server: Adopt CQRS
8+ # 0008 - Server: Adopt CQS
99
1010<AdrTable frontMatter ={frontMatter} ></AdrTable >
1111
12+ :::note Terminology clarification
13+
14+ This ADR originally used "CQRS" (Command Query Responsibility Segregation) terminology. However, our
15+ implementation more accurately reflects CQS (Command Query Separation), which is a simpler pattern
16+ focused on breaking up large service classes rather than separating read/write data models. The
17+ content has been updated to use the more accurate CQS terminology.
18+
19+ :::
20+
1221## Context and problem statement
1322
1423In Bitwarden Server, we currently use an ` <<Entity>>Service ` pattern to act on our entities. These
@@ -30,27 +39,26 @@ method parameters, which goes against our typical DI pattern.
3039- ** ` <<Entity>>Services ` ** -- Discussed above
3140- ** Queries and Commands** -- Fundamentally our problem is that the ` <<Entity>>Service ` name
3241 encapsulates absolutely anything you can do with that entity and excludes any code reuse across
33- different entities. The CQRS pattern creates classes based on the action being taken on the
34- entity. This naturally limits the classes scope and allows for reuse should two entities need to
35- implement the same command behavior.
36- https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs
42+ different entities. The CQS pattern creates classes based on the action being taken on the entity.
43+ This naturally limits the classes scope and allows for reuse should two entities need to implement
44+ the same command behavior.
3745- ** Small Feature-based services** -- This design would break ` <<Entity>>Service ` into
3846 ` <<Feature>>Service ` , but ultimately runs into the same problems. As a feature grows, this service
3947 would become bloated and tightly coupled to other services.
4048
4149## Decision outcome
4250
43- Chosen option: ** Queries and Commands**
51+ Chosen option: ** Queries and Commands (CQS pattern) **
4452
45- Commands seem all-around the better decision to the incumbent. We gain code reuse and limit class
46- scope. In addition, we have an iterative path to a full-blown CQRS pipeline, with queued work.
53+ Commands seem all-around the better decision to the incumbent, primarily because it limits class
54+ scope.
4755
4856Queries are already basically done through repositories and/or services, but would require some
4957restructuring to be obvious.
5058
5159## Transition plan
5260
53- We will gradually transition to a CQRS pattern over time. If a developer is making changes that use
61+ We will gradually transition to a CQS pattern over time. If a developer is making changes that use
5462or affect a service method, they should consider whether it can be extracted to a query/command, and
5563include it in their work as tech debt.
5664
@@ -59,3 +67,10 @@ up all at once. It's acceptable to refactor "one level deep" and then leave othe
5967are. This may result in the new query/command still being somewhat coupled with other service
6068methods. This is acceptable during the transition phase, but these interdependencies should be
6169removed over time.
70+
71+ ## Further reading
72+
73+ - [ Server Architecture] ( ../server/index.md ) - Practical guide on implementing CQS in the server
74+ codebase
75+ - [ Martin Fowler on CQS] ( https://martinfowler.com/bliki/CommandQuerySeparation.html ) - High-level
76+ summary of the CQS principle
0 commit comments