138 lines
5.5 KiB
Markdown
138 lines
5.5 KiB
Markdown
---
|
||
name: StartDTO 去重与规范
|
||
overview: 收紧 `GameLaunchSessionStartDTO` 为仅组合两个子 DTO + accessor 派生字段,简化 `launchWithSession` 编排;并在 `php-clean-code.mdc` 增加「禁止编排层双份拷贝 / DTO 重复标量」规则。
|
||
todos:
|
||
- id: refactor-start-dto
|
||
content: GameLaunchSessionStartDTO:仅 2 子 DTO + uid/providerCode/gameCode accessor
|
||
status: completed
|
||
- id: refactor-launch-logic
|
||
content: 简化 launchWithSession;findReusableLaunch 收 StartDTO;createLaunchSession 用 accessor
|
||
status: completed
|
||
- id: update-rules-dto-dup
|
||
content: php-clean-code §3 增加「编排上下文与聚合 DTO」;§8 与 agent-completion-gate 补充自查
|
||
status: completed
|
||
- id: verify-start-dto
|
||
content: docker php -l + SLOT_ROOT verify-slot-backend.sh
|
||
status: completed
|
||
isProject: false
|
||
---
|
||
|
||
# StartDTO 去重重构 + 规范加固
|
||
|
||
## 问题
|
||
|
||
[`launchWithSession`](slot-pwa/app/api/logic/GameLaunchSessionLogic.php) 中:
|
||
|
||
```php
|
||
$uid = (int) $gameLaunchDto->uid;
|
||
$providerCode = $gameLaunchContext->providerCode;
|
||
$gameCode = $gameLaunchDto->gameCode;
|
||
// ...
|
||
new GameLaunchSessionStartDTO($gameLaunchDto, $gameLaunchContext, $uid, $providerCode, $gameCode);
|
||
```
|
||
|
||
[`GameLaunchSessionStartDTO`](slot-pwa/app/api/dto/GameLaunchSessionStartDTO.php) 同时持有 `gameLaunchDto`、`gameLaunchContext` **以及** 可从二者推导的 `uid` / `providerCode` / `gameCode`,属于 **编排层双份拷贝**,违反 DRY 与 [`php-clean-code.mdc`](/Users/ray/.cursor/rules/php-clean-code.mdc)「参数应表达业务需要、聚合 DTO 不重复字段」精神。
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph before [当前]
|
||
DTO[GameLaunchDTO]
|
||
CTX[GameLaunchContextDTO]
|
||
locals[uid providerCode gameCode]
|
||
Start[GameLaunchSessionStartDTO 5 fields]
|
||
DTO --> locals
|
||
CTX --> locals
|
||
DTO --> Start
|
||
CTX --> Start
|
||
locals --> Start
|
||
end
|
||
```
|
||
|
||
## 一、代码重构
|
||
|
||
### 1. 收紧 `GameLaunchSessionStartDTO`
|
||
|
||
**文件:** [`slot-pwa/app/api/dto/GameLaunchSessionStartDTO.php`](slot-pwa/app/api/dto/GameLaunchSessionStartDTO.php)
|
||
|
||
- 构造函数仅保留:
|
||
- `GameLaunchDTO $gameLaunchDto`
|
||
- `GameLaunchContextDTO $gameLaunchContext`
|
||
- 派生字段通过 **accessor** 提供(单一数据源):
|
||
- `uid(): int` ← `(int) $gameLaunchDto->uid`
|
||
- `providerCode(): string` ← `$gameLaunchContext->providerCode`
|
||
- `gameCode(): string` ← `$gameLaunchDto->gameCode`
|
||
|
||
### 2. 简化 `launchWithSession`
|
||
|
||
**文件:** [`slot-pwa/app/api/logic/GameLaunchSessionLogic.php`](slot-pwa/app/api/logic/GameLaunchSessionLogic.php)
|
||
|
||
目标形态(可读性优先):
|
||
|
||
```php
|
||
public function launchWithSession(GameLaunchDTO $gameLaunchDto): GameLaunchSessionResultDTO
|
||
{
|
||
$launchStart = new GameLaunchSessionStartDTO(
|
||
$gameLaunchDto,
|
||
$this->resolveGameLaunchContext($gameLaunchDto)
|
||
);
|
||
|
||
$reusedLaunch = $this->findReusableLaunch($launchStart);
|
||
if ($reusedLaunch !== null) {
|
||
return $reusedLaunch;
|
||
}
|
||
|
||
return $this->createLaunchSessionAndFetchUrl($launchStart);
|
||
}
|
||
```
|
||
|
||
- 删除 `$gameLaunchContext` / `$uid` / `$providerCode` / `$gameCode` 四个中间局部变量。
|
||
|
||
### 3. `findReusableLaunch` 收参为 StartDTO
|
||
|
||
将签名由 `(int $uid, string $providerCode, string $gameCode)` 改为:
|
||
|
||
```php
|
||
private function findReusableLaunch(GameLaunchSessionStartDTO $launchStart): ?GameLaunchSessionResultDTO
|
||
```
|
||
|
||
方法内使用 `$launchStart->uid()`、`providerCode()`、`gameCode()`,避免再次拆三个标量传递。
|
||
|
||
### 4. `createLaunchSessionAndFetchUrl` 统一 accessor
|
||
|
||
- `$launchStart->uid` 等改为 `$launchStart->uid()`(及 `providerCode()`、`gameCode()`)
|
||
- Provider `launch()` 调用统一为 `$launchStart->uid()` + `$launchStart->gameLaunchContext->externalGameCode`(不再混用 `$launchStart->gameLaunchDto->uid`)
|
||
|
||
**改动范围:** 仅上述 2 个 PHP 文件,无 API / 路由变更。
|
||
|
||
## 二、用户级规范更新
|
||
|
||
### [`php-clean-code.mdc`](/Users/ray/.cursor/rules/php-clean-code.mdc)
|
||
|
||
在 **§3「参数与日志」** 后增加小节 **「编排上下文与聚合 DTO」**:
|
||
|
||
- **禁止**编排方法先把子 DTO/Context 字段拆成局部变量,再原样传入聚合 DTO(双份拷贝)。反例:`$uid = $dto->uid` 后 `new StartDTO($dto, $ctx, $uid, ...)`。
|
||
- **禁止**聚合 DTO 构造函数同时接收「可从已有只读字段推导」的重复标量。反例:同时存 `gameLaunchDto` 与 `gameCode`。
|
||
- 聚合上下文 DTO 应 **只组合** 子对象;派生值用 `uid()` / `providerCode()` 等 accessor 从子对象读取,或在用例方法内直接使用子 DTO 字段(二选一,不并存)。
|
||
- 子步骤 private 方法若需多字段,优先传 **一个** 聚合 DTO,而不是再拆 3 个标量参数。
|
||
|
||
**§8 Agent 自查** 增加:
|
||
|
||
- 是否存在「局部变量 + 聚合 DTO」双份承载同一业务字段?
|
||
- 聚合 DTO 是否包含可推导的重复标量?
|
||
|
||
### [`agent-completion-gate.mdc`](/Users/ray/.cursor/rules/agent-completion-gate.mdc)
|
||
|
||
在 Logic 自查条(现有第 5 条)中补充:**§3 编排上下文与聚合 DTO**。
|
||
|
||
## 三、验收
|
||
|
||
1. `launchWithSession` 无仅用于组 DTO 的 `$uid` / `$providerCode` / `$gameCode` 局部变量。
|
||
2. `GameLaunchSessionStartDTO` 构造函数仅 2 个参数。
|
||
3. `docker exec -w /app/www/ray/slot-pwa php82 php -l` 对相关文件通过。
|
||
4. `SLOT_ROOT=/Users/ray/Documents/project/www/ray ~/.cursor/hooks/verify-slot-backend.sh` → `PASS`。
|
||
|
||
## 范围外
|
||
|
||
- 不改动 `GameLaunchContextDTO` / `GameLaunchSessionCreateParams` 结构。
|
||
- 不修改 verify 脚本(仍依赖规则 + 自查)。
|