mirror of
https://github.com/motajs/template.git
synced 2026-05-19 00:01:11 +08:00
117 lines
7.8 KiB
Markdown
117 lines
7.8 KiB
Markdown
# 必须规则
|
||
|
||
以下规则必须时刻遵守,任何情况下都不允许违反。
|
||
|
||
1. **不擅自修改已有代码**:将我已经写好的代码视为绝对正确。除非我**明确允许**,否则**不允许任何修改**,哪怕因为接口变化或其他原因导致其中出现类型错误。若认为我的代码存在错误,应在对话中提出,而不是直接修改。
|
||
2. **不恢复我的修改**:我做的任何代码修改都是有原因的。若我在两次对话期间新增、删除或修改了部分代码,不要将其恢复。
|
||
3. **以目的驱动,而非以接口驱动**:实现前先想清楚我为什么要这样设计接口、这个接口设计的目的是什么,而不是单纯地以将接口填满为目标。
|
||
4. **遇到歧义立即提问**:若思考或实现时遇到任何问题——例如描述模糊、接口不清晰、某些地方存在歧义等——应立即向我提问,而不是按自己的想法去写。
|
||
5. **接口缺失时停止并提问**:若完成需求所需的接口尚不存在,应立即停止实现,向我提出疑问,而不是擅自新增接口来推进。
|
||
6. **按我说的方式重构**:若目标是重构某个接口,按照我指定的方式执行:
|
||
- **彻底性重构**(新旧接口完全没有重合):按正常方式全新实现,旧代码仅作逻辑与思路上的参考。
|
||
- **结构性重构**(新旧接口基本一致,细节有差距):将旧代码搬移到新接口上后进行微调。**不要**擅自新增任何参数、方法或接口,**不要**仅通过新增兼容层的方式应对重构。
|
||
7. **不要有任何“顺手”的想法**:任何时候,都不要出现顺手的想法,包括但不限于发现了一个 bug,然后**顺手**修复、发现一处类型错误,然后**顺手**修复等,这种情况下应当遵循规则 1。
|
||
|
||
# 建议规则
|
||
|
||
以下规则为建议性,尽量遵守,特殊情况下可灵活处理。
|
||
|
||
1. **合理参考建议**:我有时会在对话中给出实现建议,应合理参考,切忌滥用。
|
||
2. **以类型标注为参考依据**:实现与类型标注有冲突时,以类型标注(一般是 `types.ts`)中的内容为准。
|
||
3. **发现接口问题时提问**:若认为类型标注中的接口设计有问题,或在实现中发现缺少某些接口,应向我提问是否添加,经我同意后方可添加。
|
||
4. **接口设计兼顾合理性与便捷性**:设计接口时不仅要考虑合理性,还要考虑使用便捷性。罕见场景应当被支持,但不应与常见场景共用同一接口——这只会增加常见场景的使用难度。
|
||
5. **避免多余的非空判断与类型守卫**:若某个类型已满足目标的类型约束,不应再对其添加任何判断或过滤操作。典型例子:`Promise.all` 对数组元素类型没有任何限制,传入 `(Promise<unknown> | void)[]` 完全合法,无需多此一举地写成 `Promise.all(arr.filter(v => !!v))`。
|
||
6. **关于整个仓库的类型检查**:一般情况下**不需要**跑全仓库的类型检查,每个需求都是独立的,不会影响外部内容。只有在进行重构的时候才有此需求。
|
||
|
||
**时刻谨记上述要求,避免一个需求反复修改仍无法满足预期。**
|
||
|
||
# 开发流程
|
||
|
||
当我提出需求时,若没有明确说明直接实现或有其他明确要求,则遵循如下开发流程:
|
||
|
||
1. 阅读当前代码,分析需求,将需求整理为一个 markdown 文档,放在 `docs/dev` 目录下。文档中需明确标注需求细节,以及代码实现的大体思路。此阶段需考虑全面,遇到任何问题应向我提问并确认,不得自行假设。
|
||
2. 我会对文档进行全面阅读,确认实现细节与思路无误后,方允许开始实现。我可能会对文档进行细微调整,请在实现前重新仔细阅读最终版本。实现过程中如有任何问题,应向我提问,而不是自行决定。
|
||
|
||
## 示例文档
|
||
|
||
对于新增接口/彻底性地重构接口,大致按照以下格式编写,其余需求按照自己的理解去写即可。如某部分需要详细描述,可单独开设标题;若某个接口内容较多,也可以在文档中为其单独开一个章节进行讲述。我会使用引用块的形式在文档中提出建议或回答。Markdown 文档不需要刻意换行,我的编辑器有自动换行功能,正常写没有问题。
|
||
|
||
```md
|
||
# 需求综述
|
||
|
||
描述清楚需求的内容、动机与目的。
|
||
|
||
# 接口设计与预期
|
||
|
||
这是相当重要的一章。需要按接口逐一列出其方法与成员,分析每个成员和方法的预期使用频率(高 / 中 / 低)并说明判断依据;对于中频和高频成员,还需列出至少一个典型使用场景。
|
||
|
||
**命名长度原则**:频率越高,成员名应越短。高频成员以一个单词为宜,最多不超过两个单词;中频成员不超过三个单词;低频成员可以稍长,但不宜过长。
|
||
|
||
**频率的定义**:此处频率指**用户编写此调用的可能性或频率**,而非运行时的调用频率。例如某成员每秒被调用千次,但整个游戏中只在一处出现过,仍属低频。
|
||
|
||
示例如下:
|
||
|
||
## IObjectMover
|
||
|
||
- `IObjectMover.forward()`:预期频率**高频**。向前移动一格是地图行走、动画演出等场景的核心需求,在逻辑与演出中都会频繁出现,故为高频。典型使用场景:演出中玩家或 NPC 沿某方向连续移动。
|
||
- `IObjectMover.speed()`:预期频率**中频**。移动中修改移速有一定使用场景,但远不及 `forward`、`step` 等移动接口的频率,通常只在特殊演出或逻辑中出现,故为中频。典型使用场景:NPC 逃离怪物时先定在原地,随后逐渐加速逃跑。
|
||
- `IObjectMover.stepFace()`:预期频率**低频**。移动方向与朝向不同的常见场景(后退)已由 `backward` 覆盖,只有极特殊情况才需要此接口(如角色朝向固定但沿垂直方向平移),相当罕见,故为低频。
|
||
|
||
## 预期体量
|
||
|
||
本节应当写出预期的代码体量,并分析原因。示例如下:
|
||
|
||
预期代码体量为 200-300 行。分析如下:
|
||
|
||
- `IObjectMover` 首先需要完成计划存储与计划的定义,这些接口基本大致就是向数组中添加元素,每个方法内容都不多,整体预计在 100 行左右。
|
||
- `IObjectMover` 还需要完成移动流程的编写工作,需要根据每个移动步按照流程执行不同的行为,这一过程较为复杂,预计需要 100-200 行。
|
||
|
||
# 实现思路
|
||
|
||
按照下面的格式分条描述实现思路。
|
||
|
||
## 1. 完成 xxx
|
||
|
||
...
|
||
|
||
## 2. 完成 xxx
|
||
|
||
...
|
||
|
||
# 涉及文件
|
||
|
||
## 需要引用的文件
|
||
|
||
按照第三方库 → 其他包 → 当前包的其他文件的顺序写。
|
||
|
||
- `xxx 库`: 引用第三方库,说明引用目的,以及需要的接口
|
||
- `@user/xxx`: 引用的目的,需要这个文件的哪些接口
|
||
- `xxx.ts`: 引用此文件的目的,需要这个文件的哪些接口
|
||
|
||
## 需要修改的文件
|
||
|
||
### `@user/package/[folder/]file.ts`
|
||
|
||
除非必要或明确提出,一般不建议擅自新增公共方法或成员,必要时可以向我提问。
|
||
|
||
- [ ] 新增 `Iinterface` 接口:描述新增接口的动机与目的,会用于干什么
|
||
- [ ] 新增 `Type` 类型别名:描述新增类型别名的动机与目的,会用于干什么
|
||
- [ ] 新增 `private readonly property` 成员:描述新增成员的动机与目的,会用于干什么
|
||
- [ ] 新增 `private method(...)` 方法:描述新增方法的动机与目的,会用于干什么
|
||
- [ ] 编写 `Class.method` 方法:描述实现的大体内容
|
||
- [ ] 修改 `Class.method` 方法中的部分内容:描述修改哪些内容,修改这些内容的目的
|
||
- [ ] 重构文件结构,将 `xxx` 与 `yyy` 修改为 `zzz` 与 `www`...
|
||
...
|
||
|
||
### `@motajs/package/[folder/]file.ts`
|
||
|
||
...
|
||
|
||
# 问题
|
||
|
||
如果描述中有歧义或比较模糊的地方,可以在此列出。
|
||
|
||
1. xxxxxx?
|
||
2. xxxxxx?
|
||
```
|