Files
erqiwang_youle/docs/games/engineering/01-架构总则与分层.md
T

145 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 01 · 架构总则与分层
本篇给出七大架构总则,并落到一套**前后端参考分层**上。总则是"为什么这么设计",分层是"具体长什么样"。
所有分层里的模块名均为**示例、可自定**,约束的是**层与依赖方向**,不是名字。
---
## 1. 七大架构总则
### 1.1 单一权威数据源(Single Source of Truth)
同一业务数据**只能有一个计算/写入的地方**,其余模块只读取、不重算。多处并行计算同一结果,必随
规则演化而分叉、互相矛盾。
- 上游**算 + 写 + 校验**,下游**只读 + 消费**。
- 需要某数据时,**读权威源**,而不是"顺手再算一遍"。
- 详见 [03 篇 · 数据权威](./03-数据权威·错误处理·演进.md)。
### 1.2 单向依赖,禁止环
分层之间**自上而下单向依赖**:入口依赖编排、编排依赖领域、领域依赖数据/共享;**反向不依赖**。
- **稳定依赖原则**:越被依赖的层越应稳定(领域/共享层最稳定,入口层最易变)。
- **禁止环形依赖**:A 依赖 B、B 又依赖 A,是"职责没分清"的信号,应抽出共同依赖或调整边界。
- 双运行时下尤其致命:环依赖 + 中途 `require` 会在浏览器端崩溃(见 development-guide 的 require 守卫)。
### 1.3 职责单一、边界清晰
**一个职能只在一个模块实现**,别的模块需要它就**调用**,不"图方便"复制一份近似逻辑。
- 判据:写代码前先问"这段逻辑属于谁的职责"。属于别人的,就调用它。
- 权威能力不满足时,**在权威模块内扩展**,不要在调用方旁路重写。
- 反例:在 A 模块内联 B 模块核心算法的"简化版";同一职能两处并行演化。
### 1.4 关注点分离(Separation of Concerns)
把"不同变化原因"的代码分开,让每块**只因一个原因而改**:
| 分离维度 | 一侧 | 另一侧 |
|----------|------|--------|
| 决策 vs 机制 | "选哪个"(策略/决策) | "怎么做"(算法/规则/执行) |
| 数据 vs 表现 | 状态模型(真相) | 渲染/UI(从数据重建) |
| 编排 vs 算法 | 流程编排(controller) | 纯计算(领域算法) |
| 输入 vs 逻辑 | 收发包/参数校验 | 业务处理 |
> 例(决策 vs 机制):自动操作模块只决定"打哪张/是否碰杠胡过",**不实现**胡牌检测/听牌分析;
> 后者是领域算法,决策层只**读取其结果**。这既是关注点分离,也是职责边界。
### 1.5 对扩展开放、对修改封闭(OCP)
新增一种玩法/规则/策略/牌型,应当是**新增一段代码并注册**,而**不是**去改动已经稳定、已被测试
覆盖的核心流程。
- 手段:**注册表 + 策略**、**管线/中间件**、**工厂**(见 [02 篇](./02-可扩展性与配置化.md))。
- 收益:核心不动 → 回归风险小;扩展点清晰 → 新人能照葫芦画瓢。
- 例:分级决策框架——核心是"取上下文 → 跑管线 → 选结果",新增高级策略只是**写策略对象 +
注册 + 单测**三步,核心零改动。
### 1.6 配置优先于硬编码
**会变的、复用的、无语义的**值不写死在逻辑里,外提为常量/配置,用**数据驱动行为**。
- 分数、阈值、类型字符串、跨模块 key → 常量;成套玩法开关 → 配置对象/规则编码。
- 让"改规则"变成"改配置",而不是"改代码 + 重测逻辑"。
- 详见 [02 篇 · 配置化与去硬编码](./02-可扩展性与配置化.md)。
### 1.7 显式失败优于隐式兜底
关键路径上数据缺失,**优先报错或返回 `null`**,把问题暴露在**离根因最近**的地方;不要用
`|| 0`、`|| []`、`|| ''`、双源回退把缺失悄悄填平。
- 兜底会把 bug 藏进"看似正常"的流程里,等到很远的下游才爆发,极难定位。
- 只有**展示层、纯 UI 兼容、非关键日志**字段,才可在明确边界内用安全默认值。
- 详见 [03 篇](./03-数据权威·错误处理·演进.md)。
---
## 2. 前后端参考分层
下面是一套**成熟、可直接照搬思路**的分层。层次是稳定的,层内文件如何组织由子游戏自定。
### 2.1 后端分层(自上而下依赖)
```
┌─────────────────────────────────────────────┐
│ 入口层 Entry 收包薄委托:一操作一入口,只接住并转交 │ 易变
├─────────────────────────────────────────────┤
│ 收发层 IO 参数校验、响应构建、序列化、差异化广播 │
├─────────────────────────────────────────────┤
│ 编排层 Orchestrate 流程编排、状态机推进、跨模块协调(不含算法) │
├─────────────────────────────────────────────┤
│ 领域层 Domain 规则/算法权威实现(胡牌/听牌/计分/牌型…) │
├─────────────────────────────────────────────┤
│ 数据层 Data 对局状态、状态管理、统一访问层 │
├─────────────────────────────────────────────┤
│ 共享层 Shared 前后端逐字相同的纯逻辑与常量 │ 最稳定
└─────────────────────────────────────────────┘
依赖方向:上层 → 下层(下层绝不反向依赖上层)
```
- **入口层薄**:只做"接住请求 → 委托",不写业务;一操作一入口,不做二次路由。
- **领域层是权威**:所有"能不能胡/听什么/怎么算分"的算法只此一份,别层调用。
- **数据层是唯一状态落点**:对局状态集中管理,读写走统一访问层,避免散落。
- **共享层最底、最稳定**:见 [03 篇 · 数据权威] 与各端 development-guide 的 shared 说明。
### 2.2 前端分层(自上而下依赖)
```
┌─────────────────────────────────────────────┐
│ 入口层 Entry 平台受限入口:只解包转交,不写业务 │ 易变
├─────────────────────────────────────────────┤
│ 分发层 Dispatch 唯一收包口,按 rpc 路由到处理器(纯路由表) │
├─────────────────────────────────────────────┤
│ 处理层 Controllers 一类消息一处理器:改数据模型 / 触发表现 │
├─────────────────────────────────────────────┤
│ 状态层 Model 前端状态真相(界面从它无歧义重建) │
├─────────────────────────────────────────────┤
│ 表现层 View/Managers 渲染、动画、音频、资源(从状态派生) │
├─────────────────────────────────────────────┤
│ 共享层 Shared 与服务端同源的纯逻辑(只读同步副本) │ 最稳定
└─────────────────────────────────────────────┘
表现从状态派生:任何时刻重画都能还原正确界面
```
- **入口只转交**:平台受限入口不堆业务,逻辑全在处理层。
- **收包分发只分发**:一张 `rpc → 处理器` 路由表,不在分发口写业务。
- **数据优先、表现延后**:先落状态模型,再由表现层派生;重连=重画,与正常对局**复用同一重画路径**。
### 2.3 依赖方向自检
- 有没有"下层反过来 import/引用上层"?有 → 边界错位,重划。
- 有没有"两个模块互相依赖"?有 → 抽公共依赖或合并职责。
- 有没有"入口层里写了算法/规则"?有 → 下沉到领域层。
- 有没有"表现层里存了业务真相"?有 → 上移到状态层。
---
## 3. 本篇小结
- 七大总则:**SSOT、单向依赖、职责单一、关注点分离、OCP、配置优先、显式失败**。
- 后端六层(入口/收发/编排/领域/数据/共享)、前端六层(入口/分发/处理/状态/表现/共享),**依赖单向向下**。
- 层是稳定的,层内组织自定;判断对错的尺子始终是**依赖方向**与**职责归属**。
下一篇 [02-可扩展性与配置化](./02-可扩展性与配置化.md):把 OCP 与"配置优先"落成具体模式与判据。