---
url: /zh/start/why-wow.md
description: Wow 为编写领域模型的团队做了什么，它建立在哪些原则之上，它对部署有哪些前提，以及什么时候它不是合适的工具。
---

# 为什么选择 Wow

Wow 让团队只编写领域模型，就得到一个可以运行的系统：它的路由、契约、客户端、读模型，以及让它们保持一致的机制。领域模型之外的一切，都是 Wow 欠你的代码。

## 它做什么 {#what-it-does}

每个 Wow 系统都做三件事，其中的每个机制都源自其中之一：

1. **写入。** 命令基于最新提交的状态做出决定，变成事件，在一次原子提交中追加。对同一个聚合的两个写入者永远不会都成功：由版本决定，失败的一方会重新做一次决定。
2. **投递。** 每个提交的事件都至少一次到达每个观察者：Saga、投影、反应器、其他上下文、数仓。任何观察者都可以从头再来。
3. **使用。** 从同一个领域模型得到 HTTP 路由、OpenAPI 文档、类型化的 TypeScript 客户端、对每个聚合的状态和历史的查询、数据视图和仪表盘，无需更多代码。

## 原则 {#the-principles}

| | 原则 | 实际意味着 |
| --- | --- | --- |
| 1 | 一次写入 | 追加到日志是唯一的写入。发布、快照、投影、索引和数仓都读取日志 |
| 2 | 日志即总线 | 订阅从它自己的检查点读取日志。在上下文之间，事件以发布的事件流传递 |
| 3 | 先决定，再演化 | 决定产生事件；演化把事件应用到状态上，不做 I/O。状态可以是普通的可变对象：内核让每个版本的视图保持稳定 |
| 4 | 构建时绑定 | 编译器生成模型：运行时没有反射或扫描 |
| 5 | 协程优先 | 处处是 `suspend` 和 `Flow`；Reactor 代码仍可通过适配器工作 |
| 6 | 身份是一个值 | 聚合的上下文、类型、租户和 ID 在准入时一次性决定。每个唯一键都包含租户 |
| 7 | 读模型可重放 | 每个读模型都可以从日志重建 |
| 8 | 失败即数据 | 失败记录在台账中，并让失败的那一个聚合停放。不会跳过任何东西 |
| 9 | 一份契约 | 编译器写出的 Manifest 是路由、OpenAPI、客户端、视图和兼容性检查的来源 |
| 10 | 不绑定宿主 | 运行时与领域代码不依赖任何 Spring 类型，为其他宿主留着门。10.0 中受支持的宿主是 Spring Boot：在它之外组装节点仍是内部 API（[不用 Spring 运行](../guide/without-spring)） |
| 11 | 状态即读模型 | 每个聚合的最新状态都可以查询，无需编写投影 |

这些原则合起来，就是每个版本都必须保持的保证：

* 任何时刻的崩溃都不会丢失已提交的事实；
* 每个读模型，包括快照，都可以从头重建；
* 使用相同 ID 的两个租户永远不会相互影响；
* 在稳定状态下，存储的读取负载不随订阅数量增长；
* 在领域模型之外，你不编写任何基础设施代码。

[概念](../concepts/)从第一性原理解释其中的每一条。

## 它的前提 {#what-it-assumes}

* **每个系统一个集群。** 一个系统的所有服务运行在同一个集群中，能直接相互访问：跨服务跟随命令的等待，以及服务节点之间的通道，都建立在这一点之上。内部端口从不暴露到集群之外，集群内部的流量也要认证（[保护部署](../operate/security)）。
* **持久化存储，以及上下文之间的 Kafka。** 每个服务把它的日志保存在 PostgreSQL 或 MongoDB 上。上下文之间通过 Kafka 获取彼此的事件和命令。
* **JDK 21 和 Gradle。** 模型和契约在构建时由 KSP 和 Wow Gradle 插件绑定，这个插件没有 Maven 的对应物。

## 什么时候它不是合适的工具 {#when-it-is-not-the-right-tool}

* **几张表上的简单 CRUD。** Wow 的价值体现在决定、历史和后果都很重要的地方。规则用一个数据库约束就能表达的服务，要为它用不上的日志付出代价。
* **必须抹除的历史。** 事件从不删除，Wow 也不提供抹除或粉碎事件的方式。必须能按请求删除的个人数据，应放在事件之外、放在你可以从中删除的读模型里（[事件中的个人数据](../operate/security#personal-data-in-events)）。
* **分布在多个集群中**、无法直接相互访问的服务，或者用 PostgreSQL 或 MongoDB 之外的存储保存日志。
* **只有 Maven 的构建**，或者低于 21 的 JVM。

## 从 9.x 而来 {#from-9-x}

Wow 10 是对 9.x 的重新设计，而不是升级：一条日志取代了各种总线，编译时绑定取代了反射，失败台账取代了被确认的失败，Manifest 取代了 OpenAPI 扩展。9.x 服务只需迁移一次，源码有 Agent Skill，数据有工具（[从 9.x 迁移](../migrate/)）。

下一步：在[快速开始](./quickstart)中构建一个服务。
