easysdd-feature-fastforward
用户说"帮我做个 xxx"而且需求小的时候,本来 AI 就会直接动手写——这个技能不改变这件事。它只做一件事:在 AI 动手之前,把项目里已经沉淀的 easysdd 知识指给它,让它按需去搜,写出来的代码就能比裸写多一层保护。
所以这个技能非常轻。没有 design doc、没有 checklist、没有验收清单、不需要用户确认。看完这份指引,该读代码读代码,该写代码写代码。
动手前先扫一眼这几个地方
项目里可能已经有前人沉淀的经验、决定、探索结果。写代码之前先按需搜一下,命中就省一堆坑。
easysdd/compound/ — 经验沉淀
放 learning(踩过的坑)/ trick(好用的做法)/ decision(拍板的技术决定)/ explore(定向调研结论)四类文档。文件名带 doc_type,可以按 type 和标签过滤。
# 当前任务相关的踩坑记录
python easysdd/tools/search-yaml.py --dir easysdd/compound --filter doc_type=learning --query "关键词"
# 看有没有相关的技术决定约束了这块怎么写
python easysdd/tools/search-yaml.py --dir easysdd/compound --filter doc_type=decision --query "关键词"
# 看有没有现成的做法可以抄
python easysdd/tools/search-yaml.py --dir easysdd/compound --filter doc_type=trick --query "关键词"easysdd/architecture/ — 架构全景
DESIGN.md 是总入口,子系统拆到同目录下的其他 md 文件里。改到跨模块的东西前先看一眼相关子系统文档,避免违反既定边界。直接 Read 就行。
easysdd/tools/ — 共享脚本
search-yaml.py— YAML frontmatter 搜索(上面示范过),支持--filter、--query、--sort-byvalidate-yaml.py— YAML 语法校验,如果写了带 frontmatter 的文件就跑一下
用法细节在 easysdd/reference/tools.md。
easysdd/reference/ — 共享口径
shared-conventions.md— feature / issue / compound 的目录结构、命名、元数据字段约定tools.md— 上面两个脚本的完整用法maintainer-notes.md— 维护侧的约定(这个任务用不上一般不用看)
怎么用这些知识
动手前问自己 2 个问题:
- 这块代码以前有人栽过跟头吗? → 搜
compound/的 learning - 这块代码有没有已经拍板的写法约束? → 搜
compound/的 decision + 看architecture/相关子系统文档
命中就把相关结论融进实现(别抄,是按约束来写)。没命中就按自己判断写,这很正常——不是每个任务都有前人铺好的路。
搜不到不等于没有——换几个关键词再试。search-yaml.py 支持 --query 做全文搜,词命中范围宽。
写代码时守住这几条
这些是 design / implement 里的硬约束提炼到 fastforward 来的版本。没有 design doc 不代表可以不讲这几条——这些是让你在"直接动手写"时不偏向 AI 默认会踩的坑。
先想"放在哪儿",再想"怎么写"
动手前花 30 秒想一个问题:这次要加的东西,在项目结构里属于哪儿?
- 这件事是某个现有模块本该承担的吗?是的话在那个模块里扩展,别在外面另起
- 这件事横跨多个模块?考虑抽一层公共的,或者让某一方主导
- 已经有模块在做类似的事但名字不一样、你没注意到?
grep一下再决定 - 和现有任何模块都不太像?可能要新建独立模块——这种情况多半该切回完整 design 流程
默认踩的坑是不思考就往眼前最顺手的文件里加——加完那个文件就变成"什么都装的筐"。
扫一眼要改的文件现在什么状况
找到落点后,开写之前再看一眼要改的文件:
- 这个文件现在多长?承担了几件事?新加的是已有职责的延伸,还是第 N+1 件事?
- 这个类有多少方法?加这个方法是自然扩展,还是把类推向"什么都能干"?
状态健康就直接加。要先收拾一下(拆长文件 / 抽重函数)的话先收拾再加,但范围锁死为"只搬不改行为"。结构性问题(职责要重划 / 模块要拆合)就停下来告诉用户这个比想的复杂、建议回 design 流程。
硬塞功能进一个已经不干净的文件,得到的是一个更长更不干净的文件——这是 AI 的默认偏好,要明着抵抗。
默认写最少的代码
只写用户当前明确要的那点东西。不顺手加:
- "以后可能要用"的配置项 / 参数开关
- 没人要的防御性兜底 / try-catch
- 预留的抽象层 / 接口 / 工厂
- 用户没提的边界处理
写完一段觉得"是不是还得加点 X 才完整"——先问 X 是不是用户能感知到的,不是就别加。多出来的代码不是中性的,是后人维护时要读懂、要怀疑、要担心漏了哪条不变量的负担。
只动该动的,不顺手"改善"邻居
打开一个文件改某个函数时,只改那个函数。同一个文件里别的函数风格丑、命名怪、注释陈旧——除非和这次改动直接冲突,否则别碰。新写的代码风格匹配当前文件已有写法,哪怕你自己平时不这么写。
看到值得改的别处,记下来告诉用户"顺手发现:{文件:行号} {问题},不在本次范围",让用户决定要不要单独做。
新逻辑默认放新文件
新增的内聚逻辑单元默认建独立文件,而不是往已有文件追加。判断口径:这个新逻辑以后会被其他地方引用吗?会的话放新文件;只是当前一处用的小工具函数可以就近放。
不打补丁分支
写到一半冒出 if (特殊情况) {特殊处理} 这种结构,停。
这种分支冒出来基本只有一个原因:思路没覆盖到这种情况。继续硬写得到的是"为了让代码能跑而加的特殊逻辑",下次别人改这块时根本不知道这个分支为什么存在。正确做法是把这个情况想清楚再继续——要么改数据结构让它不需要特殊处理,要么明确承认它是边界情况并加注释说明为什么特殊。
反射信号触发就停
下面几种信号一出现就要停下来重新评估,不是硬着头皮写下去:
- 往一个已经 > 300 行的文件继续追加
- 往一个已经 > 10 个方法的类里再加方法
- 一个函数做的事越来越多,超过一屏
- 要写第二段"跟上面那段基本一样但改了两个变量"的代码
- 函数参数加到第 4 个
- 往
utils.ts/helpers.ts这种万能 util 里继续堆东西 - 要新起一个概念名(类型 / 函数 / 关键变量)时,先
grep看有没有同名或近义的命名
完整清单看 easysdd/reference/shared-conventions.md 第 7 节(代码质量反射检查)。
不做什么
- 不写 design doc——这是 fastforward 的整个意义所在。要 design 就去
easysdd-feature-design - 不写 checklist / acceptance——同上
- 不跟用户确认方案——用户让你做小功能就是不想等你开会
- 不在
easysdd/里留下新文件——除非写代码过程中发现了值得沉淀的坑或技巧,那另起一次对话用easysdd-learning/easysdd-tricks去写
什么时候跳出 fastforward
干到一半发现下面任一情况,停下来告诉用户"这个比想象的复杂,建议切回完整 feature 流程":
- 改动涉及 3 个以上子系统
- 发现需要引入新术语或和现有术语冲突
- 要动
easysdd/architecture/里既定的模块边界 - 用户追加的要求让范围翻倍
切回完整流程的方式:触发 easysdd-feature-design 技能,从 design 阶段重新走。已经写了一部分代码没关系,在 design 里标注"已部分实现"即可。
容易踩的坑
- 完全跳过知识检索就写——这个技能存在的唯一理由就是让你搜一下再写,不搜就等于没加载这个技能
- 把搜到的 learning/decision 当"参考资料"而不是"约束"——decision 是拍过板的,违反它要么重新 decision 要么别做
- 开始写 design doc——fastforward 就是不写 design,想写就去 design 技能
- 发现任务变复杂还硬在 fastforward 里推——切回完整流程成本远低于带着错误方案改到底