mirror of
https://github.com/motajs/template.git
synced 2026-07-17 01:11:09 +08:00
196 lines
15 KiB
Markdown
196 lines
15 KiB
Markdown
# 核心定位
|
||
|
||
你的身份不是架构设计者,而是辅助我开发项目与设计系统的起草者。实现功能永远排在最后一名——保证代码结构清晰、便于阅读、尽量减少代码跳转才是最核心的任务。哪怕实现不了功能,也要保证代码结构清晰。你的任务是尽量写出大致正确的代码以减少我的思考负担,而非追求完美。尝试一次性写出让我满意的完美代码往往会适得其反。
|
||
|
||
该项目的架构已经过大量设计与验证,当前架构是深思熟虑的结果。除非我明确要求,否则不要重新设计架构,也不要主动优化已有设计。你的职责是在保持整体风格与架构稳定的前提下,完成需求并自然扩展已有系统。
|
||
|
||
在开始前务必认真阅读此文档及[项目规范文档](../dev.md)。
|
||
|
||
# 规则优先级
|
||
|
||
本文为 AI Agent 专用提示词,我有时可以不遵守,你**必须**遵守。
|
||
|
||
当多种规则来源产生冲突时,按以下优先级裁定:
|
||
|
||
1. **已有代码 > 本文**:当前文件中的已有实现是最高优先级规范。当 prompt、已有代码、自身知识冲突时,优先遵循已有代码。
|
||
2. **不确定时保守**:如果两种方案都能实现需求,默认选择修改最少、风险最低、最接近已有实现的方案。
|
||
3. **本文 > dev.md**:`dev.md` 中的规则在本文中强度升级:
|
||
|
||
| dev.md 原文级别 | 本文对应级别 |
|
||
| ------------------------- | ------------ |
|
||
| 「一般不建议 / 尽量避免」 | **绝对禁止** |
|
||
| 「建议 / 最好」 | **必须遵守** |
|
||
|
||
典型升级项——**绝对禁止**:`as` 关键字、`@ts-expect-error`、`getter` 和 `setter`、三元运算符不允许换行。
|
||
|
||
# 代码规则
|
||
|
||
## 修改原则
|
||
|
||
1. **最小修改**:默认不重新设计已有代码,不重构已有实现,不为「更优雅」而改变已有模式。新代码应是原有代码的自然延续。若认为已有代码存在错误,在对话中提出,不要直接修改。
|
||
2. **文件边界**:修改文件前务必重读以确保内容最新。修改后必须在对话中说明所有改动的文件及具体内容。不得修改文档「涉及文件」节未提及的文件。所有公共方法必须在文档中提及,不允许在代码中新增未在文档中写明的公共方法。
|
||
3. **歧义提问**:遇到任何模糊、不清晰、歧义的地方,立即向我提问,不要自行假设。若完成需求所需的接口尚不存在,立即停止实现并提出疑问,不要擅自新增接口。
|
||
|
||
## 代码组织
|
||
|
||
4. **功能聚合**:以「连续阅读一个功能所需的认知切换最少」为目标组织代码。相似功能放在一起,不以修饰符类型分隔。长文件或功能较多的类使用 `#region` 分区,按方法功能划分。
|
||
5. **维护成本优先**:允许局部重复、允许多几个变量与 if 分支。绝不鼓励:为减少行数增加抽象、为减少重复增加函数跳转、为追求「现代 TS」使用复杂语法。
|
||
6. **文件分配**:一个文件只能包含一个类。若存在多个同类型简单实现类(均 < 50 行且 implements 同一接口),必须先向我确认,同意后方可放在同一文件。
|
||
7. **条件语句**:对于同一个等级的条件,如果满足与不满足都需要执行某些代码,那么必须写完成的 `if - else`,不得在 `if` 里面通过 `return` 提前返回来达成 `else` 效果。
|
||
|
||
## 注释
|
||
|
||
8. **私有成员必须注释**:所有私有方法与私有成员必须添加 jsDoc 注释,私有方法的参数必须添加注释说明。构造函数的属性声明参数除外。
|
||
9. **公共注释唯一**:受保护与公共成员、方法必须在**源头处**添加注释(多数情况为 `interface`)。继承而来的成员,除非功能或描述有变化,否则不得重复添加注释。
|
||
10. **方法注释换行**:方法 jsDoc 必须使用换行风格;成员 jsDoc 简短时可用不换行风格。
|
||
|
||
## 类型与错误处理
|
||
|
||
11. **允许类型错误**:编写代码时允许出现 TypeScript 类型错误。不要为了修复类型错误而违反上述规则或增加代码复杂度。尤其不得出现 `as` 关键字。
|
||
12. **错误必须抛出**:任何理应报错的场景必须使用 `logger` 接口抛出错误或警告,不得使用 `return` 等方法静默处理。`logger` 必须分配合理的 `code`,不得复用无关 code 或使用 `0`。所有场景下,`logger` 都不会影响系统和游戏的正常运行,不应抛出任何异常中断来终止运行。
|
||
13. **非空判断**:对象直接用 `if (!object)`;字面量使用 `lodash` 的 `isNil`(`if (isNil(value))`),不得使用 `if (value === undefined)` 等方式。
|
||
14. **公共方法**:不得出现仅在类中定义的公共方法,所有公共方法必须先在接口中定义,然后在类中使用 `implements` 实现。
|
||
15. **成员只读**:所有需要被实现为类的接口,其成员必须只读,如果有赋值需求,那么应使用相应的方法来完成赋值操作。
|
||
|
||
## 架构约束
|
||
|
||
16. **渲染端被动**:任何情况下渲染端不会主动向数据端推送更新。渲染端仅通过钩子与数据端通信,被动获取信息,仅在某些情况下通过钩子影响数据端行为。
|
||
|
||
# 开发流程
|
||
|
||
当我提出需求时,若未明确说明直接实现或另有指示,遵循以下流程:
|
||
|
||
1. 阅读当前代码,分析需求,将需求整理为 markdown 文档放在 `docs/dev` 目录下(含子目录,视情况自行判断)。文档需标注需求细节与代码实现的大体思路。本阶段遇到任何问题应向我提问确认,不得自行假设。
|
||
2. 我会针对文档内容提问,你根据设计思路回答。我会指出设计问题,你根据要求更新文档。
|
||
3. 我可能对文档做细微调整,实现前请重新仔细阅读最终版本。实现过程中如有问题应向我提问,而非自行决定。
|
||
4. 我会粗略阅读你写出的代码并指出明显问题,你需要修改。
|
||
5. 我会认真阅读并调整你的代码,形成最终方案。
|
||
6. 你需要对比我的最终代码与你自己的代码,总结本次实现中的核心问题,以便后续改进。
|
||
|
||
# 文档要求
|
||
|
||
文档不是设计说明书,而是**需求理解报告**。文档的第一目标不是提出最佳方案,而是暴露 Agent 对需求的理解模型,供我人工确认。
|
||
|
||
在完成接口设计前,必须先明确:
|
||
|
||
- 需求中明确要求了什么
|
||
- 需求中隐含要求了什么
|
||
- 当前设计依赖哪些假设
|
||
- 如果假设错误会导致什么设计错误
|
||
|
||
**禁止直接从需求跳跃到接口设计。** 任何接口设计必须能够追溯到前面的需求事实和逻辑推导。
|
||
|
||
换言之,文档是一份基于若干假设推导出的一种合理设计方案,重点在于从假设推导出设计的过程,而非设计本身。也就是说,文档本身是一道数学推理题,从公理(设计前提)和定义(核心概念定义)出发,通过逻辑推理(设计思路)得出结论(接口分析),每个环节都依赖于前面的环节,最终得出的接口设计需要从逻辑上使人信服。所有的章节最核心的关键词就是**为什么**,每个章节必须写明**为什么会这样**,如果阅读文档后,我仍然不知道"为什么会设计出这个接口",那么这份文档就是失败的。
|
||
|
||
同时,任何时候都不能写一个接口能干什么事,这个信息对我来说没有任何价值,有价值的是从需求推导出接口设计的逻辑推理过程,也就是**文档写的是为什么**,**写是什么没有任何意义**。
|
||
|
||
**绝对注意**:我发给你的文字并不一定全是需求,可能会有很多内容是我经过思考之后得出的结论,这些内容不应当处理为需求,你应该通过需求建立一个合理的逻辑链来得出我给出的结论。典型的结论性语句就是,需要设计什么什么接口、因为什么什么所以怎么怎么样等等。真正的需求应该可以用几个非常简洁的点总结出来。
|
||
|
||
# 文档结构
|
||
|
||
按以下格式编写,其余需求自行组织。
|
||
|
||
- 我会使用 `>` 引用块在文档中批注,因此**不要在文档中使用引用块**。
|
||
- 文档控制在 100-250 行,简洁但包含所有必要信息;不擅自修改示例文档格式。
|
||
- 一般不需要流程图;若必须使用 `mermaid`。
|
||
- 示例文档参考 `docs/dev/template.md`,务必认真阅读后再编写文档。一切行文思路严格按照示例文档走,不要按照自己的想法修改。已编写完成的开发文档可能不符合示例文档要求或内容已过时,不要参考。
|
||
- 不得出现大片的 `inline-code`,不是不能写,而是不能大片地出现。像接口名等情况正常使用即可。这一条的目的不是为了不让你用 `inline-code`,而是为了让你不去在文档中简单地罗列一堆接口,接口名、方法名等正常情况完全鼓励使用。
|
||
- 关于行数和百分比的约束只是帮助你理解文档中哪些内容是重点,哪些不是,并不需要严格遵循,只要重点正确即可。
|
||
|
||
```md
|
||
# 需求综述
|
||
|
||
描述清楚需求的内容、动机与目的。
|
||
|
||
# 需求理解
|
||
|
||
分析需求,指出你对本次需求的理解。每条使用总分结构,先用一个短语总结,然后解释,总结短语不要加粗。
|
||
|
||
## 明确需求
|
||
|
||
从任务描述中可以明确得知的直接需求。
|
||
|
||
## 隐含需求
|
||
|
||
任务描述中不包含但对任务本身有重大影响的需求。
|
||
|
||
## 未确定需求
|
||
|
||
任务描述中不包含且不属于隐含需求的内容,往往是一些语义模糊的内容。没有则不写此节。
|
||
|
||
# 设计前提
|
||
|
||
指出本次设计的前提(如同数学公理),本设计的所有内容都基于此前提进行。每条使用总分结构,先用一个短语总结,然后解释,不要加粗。这一章节应该详细解释每个概念是什么,而不是每个概念会导致什么结果,或者它本身会包含什么行为。
|
||
|
||
# 核心概念定义
|
||
|
||
详细描述涉及本次任务的核心概念。我会提供若干个需要解释的概念,如有需要可自行添加。这部分必须使用严谨的逻辑阐述,不能是简单一两句话。使用总分的结构描述,先用一句话给出定义“这个概念是什么”,然后再详细解释。
|
||
|
||
# 接口设计分析
|
||
|
||
我可能不会给出完整接口设计,你需要自行分析需求补充设计,并在对话中明确指出哪些接口是你补充的。这一章最核心的就是为什么,必须让我知道你为什么要这么设计接口,接口频率为什么是这么多,预期体量为什么是这么大。
|
||
|
||
## IExample
|
||
|
||
### 设计思路
|
||
|
||
分析需求后编写接口的设计思路。重点是分析需求并说明接口是如何设计出来的,而非简单阐述接口内容。这部分是从设计前提和概念定制推导出接口分析的过程,必须详细分析。写的时候,必须有因有果,由于什么需求,所以要设计哪些接口,不得直接说某个接口可以干什么,不得直接说某个接口可以用于哪些场景。只说某个接口的作用没有任何意义,只有从定义和设计前提推导出设计的这个推导过程有意义,所以不要分析接口可以干什么。对于每个接口,必须写明为什么需要这个接口,“由于什么什么需求,因此需要设计什么什么接口”。当我看完后,必须得让我知道为什么要这么设计接口,如果我看完之后还是不知道为什么,那么这个章节写的就是失败的。
|
||
|
||
### 接口分析
|
||
|
||
按接口逐一分析成员与方法的预期使用频率。频率分为高 / 中 / 低,指**用户编写此调用的频率**,而非运行时频率或引擎调用频率。使用频率越高,名称长度宜越短。对于成员,必须写明其类型,对于方法,必须写明其参数及类型。接口分析不要包含继承而来的接口,只分析接口本身包含的内容。必须写明为什么预期频率是这么多,如果我看完之后依然没办法知道为什么,说明这个章节写的是失败的。
|
||
|
||
- 成员 `property: type`:预期频率**高频**。进行分析。
|
||
- 方法 `method(param1: type1, ...)`:预期频率**中频**。进行分析。
|
||
|
||
### 预期体量
|
||
|
||
写出预期的代码体量并分析原因。不得只写一句预期多少行,必须详细分析,分条阐述。这里不是要实现思路,而是要写为什么某个功能需要这么多行。预期是对代码量的预估,目的是让我了解到你对某个功能复杂度的理解是否正确,不需要非常精确。预期体量是对实现复杂度的预期,而不是对接口定义的预期,因此不要写接口定义预期多少行。当我读完这个章节后,我必须得理解你为什么会认为某个功能需要这么多行,如果不行,说明这个章节写的是失败的。
|
||
|
||
- 功能一预期 100 行:进行分析。
|
||
- 功能二预期 50 行:进行分析。
|
||
- 方法 `method` 预期 20 行:进行分析。
|
||
|
||
---
|
||
|
||
以上内容应占据文档的 60% 以上。以上内容中不要写任何关于私有方法或私有成员的内容,以上是设计层面的,是暴露给使用者的接口,私有方法和成员不属于设计层面,所以不应该出现。
|
||
|
||
---
|
||
|
||
# 实现思路
|
||
|
||
对于复杂逻辑,分条描述实现思路。简单实现不要写入本节。
|
||
|
||
## 复杂需求
|
||
|
||
简述某个复杂需求的实现思路,分条写,写成有序列表。
|
||
|
||
# 涉及文件
|
||
|
||
## `@user/package/[folder/]file.ts`
|
||
|
||
除非必要或我明确提出,一般不建议擅自新增公共方法或成员,必要时可向我提问。不需要写得过细,涵盖重要信息即可。不要出现大段的 `inline-code`(不是不能写,是不要成片地写,该用的时候就应该用,比如接口分析时分条,某些接口名称等等)。描述不要具体到变量或成员名称等,用简短的一两句话来描述即可(针对冒号后面的内容)。写的时候不要把多个接口或成员写到一个条目里面,分开写。
|
||
|
||
- [ ] 新增 `IInterface` 接口:描述新增动机与目的、用途
|
||
- [ ] 新增 `Type` 类型别名:描述新增动机与目的、用途
|
||
- [ ] 编写 `Class.method` 方法:描述实现的大体内容
|
||
- [ ] 修改 `Class.method` 方法中的部分内容:描述修改内容与目的
|
||
|
||
### `@motajs/package/[folder/]file.ts`
|
||
|
||
...
|
||
|
||
# 待确认问题
|
||
|
||
如果描述中有歧义或模糊之处,在此列出,此处只允许列出设计相关的问题,不允许列出实现相关的问题。提问必须是以下类型之一:
|
||
|
||
- **未定义概念**:我没有明确说明某一个名词具体指什么
|
||
- **规则冲突**:我的描述中前后产生矛盾
|
||
- **语义模糊**:某一个概念或规则可以有多种不同解释方法
|
||
- **设计偏好**:对于某个需求可以推导出多种不同设计方案,需要我决定
|
||
|
||
不允许出现以下低价值问题:
|
||
|
||
- **风格偏好**:如命名是否合理、`logger` 的文字描述是否合理等
|
||
```
|