# 0008 - Server: Adopt CQRS

{% hint style="info" %}
对应的[官方页面地址](https://contributing.bitwarden.com/architecture/adr/server-CQRS-pattern)
{% endhint %}

| ID：  | ADR-0008   |
| ---- | ---------- |
| 状态：  | 进行中        |
| 发表于： | 2022-07-15 |

## 背景和问题陈述​ <a href="#context-and-problem-statement" id="context-and-problem-statement"></a>

在 Bitwarden Server 中，我们目前使用 `<<Entity>>Service` 模式来作用于我们的实体。这些类最终成为了涉及实体的所有操作的垃圾场：导致[臃肿](https://refactoring.guru/refactoring/smells/bloaters)和[耦合](https://refactoring.guru/refactoring/smells/couplers)。有两个事实帮助我们确定了当前的设计：

* 我们使用实体模式来表示存储在数据库中的数据，并使用 Dapper 或实体框架自动绑定这些实体类。
* 我们使用基于构造函数的依赖注入来将依赖项传递给对象。

上述两个事实意味着，如果不接收所有必要的状态作为方法参数，我们的实体就无法运行，这与我们典型的 DI 模式背道而驰。

## 考虑的方案​ <a href="#considered-options" id="considered-options"></a>

* **`<<Entity>>Services`** -- 上面讨论过了。
* **查询和命令** -- 从根本上来说，我们的问题是 `<<Entity>>Service` 名称完全封装了您可以对该实体执行的任何操作，并且排除了不同实体之间的任何代码重用。CQRS 模式根据对实体采取的操作创建类。这就自然而然地限制了类的范围，并在两个实体需要实现相同的命令行为时允许重复使用。<https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs>。
* **基于功能的小型服务** -- 这种设计会将 `<<Entity>>Service` 分解为 `<<Feature>>Service`，但最终会遇到同样的问题。随着功能的增加，该服务将变得臃肿，并与其他服务紧密耦合。

## 决策结果​ <a href="#decision-outcome" id="decision-outcome"></a>

选择的方案：**查询和命令**。

对于现任者来说，命令似乎是更好的决定。我们获得了代码重用并限制了类的范围。此外，我们还拥有一条迭代路径，可以通过队列工作实现完整的 CQRS 管道。

查询基本上已经通过存储库和/或服务完成，但需要进行一些明显的重组。

## 过渡计划​ <a href="#transition-plan" id="transition-plan"></a>

随着时间的推移，我们将逐渐过渡到 CQRS 模式。如果开发人员正在进行使用或影响服务方法的更改，他们应该考虑是否可以将其提取到查询/命令中，并将其作为技术债务包含在他们的工作中。

当前的领域服务规模庞大且相互依赖，一次性将它们全部分解可能不太现实。重构「更深一层」并保留其他方法是可以接受的。这可能会导致新的查询/命令仍然在某种程度上与其他服务方法耦合。在过渡阶段，这种情况是可以接受的，但随着时间的推移，这些相互依赖关系应该被移除。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ppgg.in/architecture/adr/0008-server-adopt-cqrs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
