1. 散落在各处的 Prompt 字符串,到底在哪些环节咬人
先说结论:Prompt 模板版本化管理这件事,绝大多数团队都是被咬疼了才回头的。我见过太多项目,Prompt 一开始就一行字符串,写在业务代码里,prompt = "你是一个专业的...",改起来毫不费力,谁都觉得没必要上体系。等到项目跑了两三个月,同一套业务里散着七八份 Prompt,有的在 Python 文件里、有的在配置表里、有的在某个同事的本地记事本里,还有人直接在测试环境手改线上取值——这时候问题就不是"优雅不优雅",而是"线上效果为什么昨天还好今天就不对了"。
所谓 Prompt 模板版本化管理,说白了就是把 Prompt 当成一份有身份、有历史、有责任人的工程资产来对待:它有唯一标识,有明确的版本号,有变更记录,有配套的评测,有可回滚的发布路径。它解决的不是"写 Prompt"的问题,而是"一群人、几个月、几十次修改之后,你还能不能准确说出线上跑的是哪一份、为什么变成这样、改回去要改哪里"。这件事对独立开发者也有价值,但真正离不开它的是有协作、有灰度、有线上流量压力的团队场景。
关键词里的"可追溯"三个字其实很重。可追溯不只是"有记录",而是你拿到任何一个线上请求的日志,都能反推出当时用的模板内容、渲染参数、模型标识和关键采样参数,然后本地复现出基本一致的结果。缺任何一环,追溯都是假的。
1.1 三幕我亲历过的翻车现场
第一幕是"改好了但没人知道"。某团队的客服摘要功能,一位同学在本地把 Prompt 里的输出格式从"自然段"改成"三段式小标题",人工看了十几条效果确实好,直接合进主干。两周后下游做结构化解析的模块开始大量失败,排查了半天才发现是格式变了,而下游的解析规则还是老的。问题不在于改得对不对,而在于这次变更没有任何"影响面提示",也没有回归用例去覆盖格式合规率这个指标。
第二幕是"回滚回了个寂寞"。线上效果波动,值班同学按照流程把 Prompt 回滚到上一版——但"上一版"是从某个文档里复制出来的旧文本,粘回去之后效果更差了。原因是那版文本在文档里是三个月前的,中间还有一次没记录的小改动,真实线上跑的是"文档版 + 某次热修"。没有版本号,回滚就变成了猜。
第三幕是"幽灵变更"。这次最阴。Prompt 文本一个字都没动,但效果整体偏了一截。查了半天发现是共用的 few-shot 示例片段被人优化了,主模板通过 include 引用了它,而片段是独立维护的,没有跟着主模板一起锁定版本。文本层面 diff 是空的,行为层面已经变了。这类问题如果没有"渲染后内容哈希"这种机制,几乎不可能靠人眼发现。
这三幕指向的是同一件事:Prompt 的变更粒度比代码细、比配置模糊。它不像代码有编译器兜底,也不像配置大多是确定性取值。它是一段自然语言,改一个形容词就可能改变模型行为,而改动本身在评审里看起来"只是措辞优化"。
1.2 "我觉得比之前好"是最危险的判断依据
Prompt 调整有一个特别大的陷阱:反馈是主观的、样本是少量的、结论是即时的。你改了五处措辞,随手测了十条,感觉好像顺了一点——这个"顺了一点"包含大量确认偏误。更麻烦的是,Prompt 的改动经常是"这边好了那边坏":你让模型输出更简洁,格式合规率上去了,但关键信息召回率掉下来了;你加了更强的约束,拒答率上去了,误拒也跟着上去了。
所以版本化管理里,评测不是附属品,而是让"版本"这个概念成立的前提。没有评测,"v1.3 比 v1.2 好"这句话就没有意义,版本号也就退化成单纯的存档编号。我在后面第 4 节会专门讲评测集怎么攒、指标怎么设计,这里先立个观点:每一次版本号递增,都应该能对应到一组可以复跑的数字,哪怕这组数字只有二三十条用例,也比"感觉好"强得多。
1.3 版本化真正要交付的四个能力
把这套东西拆开,实际要交付的能力就四条,后面所有章节都是围绕它们展开的:
| 能力 | 具体含义 | 缺失后的典型症状 |
|---|---|---|
| 可复现 | 给定版本号 + 参数,能还原出完全一致的渲染结果 | 本地测好线上不对,互相怀疑环境 |
| 可比较 | 两个版本的差异能被结构化地看出来,包括间接引用 | 评审只看措辞,漏掉格式与变量变更 |
| 可回滚 | 一键切回任意历史版本,且有明确验证手段 | 回滚靠手抄备份,越滚越乱 |
| 可协作 | 谁改的、为什么改、影响哪些调用方,一目了然 | 多人覆盖修改,责任无法定位 |
这四条里,最容易被低估的是"可比较"。人眼 diff 两段中文,注意力天然集中在字面改动上,对"变量名从user_query改成query""示例从 3 条减到 2 条""输出格式从 JSON 改成带 markdown 代码块的 JSON"这类结构性变化敏感度很低,而这些恰恰是最容易打断下游的。
2. 把 Prompt 从代码里搬出来:文件形态与目录切分的取舍
第一步动作很朴素:把 Prompt 从业务代码的字符串常量里搬出来,变成独立文件。但搬出来之后马上会遇到一连串选择:用什么格式、元数据放哪、变量怎么声明、片段怎么复用、目录怎么切。这些选择会直接决定后面版本化好不好做,选错了会反复返工。
2.1 单份 Prompt 文件应该长什么样
我倾向的形态是"元数据头 + 正文"的单文件结构,元数据用 YAML front matter,正文就是纯文本模板。这样做的好处是:一份文件自包含,评审时 diff 直观,工具链解析成本低,非工程同学也能直接编辑正文而不用碰代码。
一份实际可用的文件大致长这样:
--- id: cs.summary.v2 version: 2.3.1 owner: team-a status: active model_hint: general-chat params: temperature: 0.2 max_output_tokens: 800 variables: - name: user_query required: true - name: history_digest required: false default: "(无历史上下文)" includes: - snippet/policy_tone@1.2.0 changelog: | 2.3.1 修正示例中的错别字,无语义变更 2.3.0 增加两条边界示例,覆盖空输入场景 2.2.0 输出结构由自然段改为三段式标题 tags: [summary, customer-facing] --- 你是一名摘要助手。请基于下面的用户问题与历史摘要,输出三段式结论……几个字段值得单独解释一下它们为什么必须存在。id是稳定标识,它不随版本变化,是所有引用方(代码、配置、日志)唯一应该硬编码的东西;version是内容版本,只在内容语义变化时递增;variables是静态契约,渲染前可以先做一次变量校验,把KeyError从运行时提前到加载时;includes显式声明依赖的外部片段及其版本,这直接对应前面说的"幽灵变更"问题——只要 include 写死了版本号,片段升级就不会静默影响主模板。
这里有个常见的分歧:有人主张把元数据和正文拆成两个文件(.yaml+.md),理由是元数据可以被程序化批量处理。我的实测结论是单文件更好,因为评审时的上下文完整性比批量处理便利更重要。拆开之后,改正文的人经常忘记同步元数据里的版本号和 changelog,反而制造了不一致。
2.2 变量、片段复用与渲染层的边界
变量这件事,看起来只是字符串替换,实际有两个坑。
第一个坑是变量值本身的注入风险。用户输入里如果带了类似指令的文本,直接拼进模板就可能改变模型行为。工程上的处理不是靠 Prompt 里写"忽略用户输入的指令"这种软约束,而是在渲染层做结构隔离:把用户内容放在明确的分隔标记之间,并在渲染时对分隔标记做转义或剥离。这部分逻辑属于渲染层,不属于模板正文,模板里只保留占位符。
第二个坑是变量缺失时的默认行为不统一。有的调用方传空字符串,有的传None,有的干脆不传。渲染层必须统一策略:required: true的缺失直接抛错并拒绝调用,required: false的缺失用default填充。这条规则听起来很基础,但我见过不止一个项目因为"某处漏传变量导致模板里出现了字面量{user_query}",模型把这个占位符当成内容的一部分,输出了一堆莫名其妙的东西,排查了两天才定位。
片段复用要克制。我建议只允许一种复用方式:带版本锁定的静态 include,渲染时先展开片段再替换变量,展开结果参与哈希计算。不要做条件包含、不要在片段里再嵌套变量替换逻辑、不要允许片段引用片段超过两层。原因很实际:复用层级一深,任何一次排查都要在四五个文件之间跳,认知负担远超收益。二十行的重复文本,多数时候比一层抽象更划算。
2.3 目录按业务域切,不按调用链路切
目录结构上,我踩过的坑是先按技术调用链路切,比如preprocess/、inference/、postprocess/。跑了半年就发现不行:一个业务功能的 Prompt 被拆散在三个目录里,改个需求要动三处,而且这三处的版本号还得手动对齐。
改成按业务域切之后就顺了:
prompts/ cs/ summary/ main.prompt.md extract.prompt.md CHANGELOG.md classify/ main.prompt.md content/ rewrite/ main.prompt.md snippet/ policy_tone.prompt.md output_json.prompt.md _deprecated/cs是客服域,summary是具体功能,同一个功能相关的模板放一起,版本节奏天然一致。snippet单独放共享片段,_deprecated放已下线但需要保留追溯的模板——不要直接删,删了历史日志里的id就指不到东西了。
还有一条经验:目录层级不要超过三层。超过三层说明你的业务域划分有问题,或者你在用目录结构表达本应该写在tags里的信息。
3. 版本号不是装饰:语义化规则在 Prompt 上的适配
代码里大家习惯了语义化版本,但直接搬到 Prompt 上会水土不服。代码的"破坏性变更"有明确的技术定义(接口签名变了、返回类型变了),Prompt 的"破坏性"是行为层面的,判定标准必须重新定义,否则每个人理解不一样,版本号很快就失去信息量。
3.1 三类变更的判定标准
我给团队定的规则是这样的,核心思路是看"调用方需不需要跟着动"和"输出契约有没有变":
| 变更类型 | 判定标准 | 版本位 | 示例 |
|---|---|---|---|
| 结构性变更 | 变量增删改名、输出格式变化、任务定义调整、角色设定变化 | 主版本 +1 | 输出从自然段改为固定字段 JSON |
| 行为性变更 | 增加/删除示例、补充约束条件、调整措辞影响判断倾向 | 次版本 +1 | 新增"不确定时明确说明"的要求 |
| 非行为变更 | 错别字、空格、注释、元数据里的 tags | 修订号 +1 | 修正"的得地"误用 |
执行这套规则有三个反复出现的争议点,我提前给结论。
第一,"调整措辞算不算行为性变更"——算,只要它可能影响模型判断。判断方法很简单:把新旧两版跑同一批评测用例,如果有任何一条输出不同,就按行为性变更处理。这个判定可以自动化,不需要靠讨论。
第二,"删掉一条示例算主版本还是次版本"——算主版本。因为示例数量变化会改变输出长度分布和格式遵循度,下游如果对长度敏感就会受影响。这条规则刚推行时有人反对,觉得太严格,但严格执行两个月后,下游因格式问题导致的故障明显少了。
第三,"模型版本切换算谁的版本"——不算 Prompt 的版本,但必须记录。模型切换是外部依赖变更,应该单独记在发布记录里,并且触发一次全量评测。我最怕看到的情况是:Prompt 版本号没动,模型换了一版,效果飘了,所有人都在 Prompt 里找原因。
3.2 内容哈希:给"文本没变但行为变了"上一道锁
版本号是人给的,哈希是算出来的。两者必须同时存在,因为它们防的是不同的问题:版本号防"改动没记录",哈希防"记录不完整"。
具体做法是,在渲染完成后对渲染后文本 + 模型标识 + 关键采样参数做一次哈希,把这个哈希作为运行时指纹写进日志。这样即使有人绕过了流程直接改了文件内容(没有递增版本号),哈希也会变,你能立刻发现"版本号一样但内容不一样"。反过来,如果哈希一样但效果不同,那问题一定在模型侧或者采样参数侧,排查方向立刻就清晰了。
这里有个细节容易被忽略:采样参数里的temperature、top_p、max_output_tokens必须纳入哈希,但不要纳入随机种子之外更多的东西,否则哈希会因为无关参数抖动而频繁变化,反而失去对照价值。我的做法是把"影响输出分布的参数"纳入,把"影响传输和超时的参数"排除。
3.3 变更日志写成给下一个人看的
changelog最常见的写法是"优化提示词""调整表述",这种记录等于没写。有用的写法必须回答三个问题:改了什么、为什么改、验证了什么。
我要求每条记录至少包含一句"改了什么"和一句"依据"。比如:
2.3.0 新增两条空输入边界示例,覆盖上游偶发空查询导致的空输出;回归集 42 条全部通过,格式合规率从 91% 提升到 98%2.2.0 输出结构由自然段改为三段式标题,配合下游结构化解析上线;已同步通知解析模块负责人
第二句的价值在后来的复盘里体现得特别明显:半年后有人问"为什么当初要改格式",直接翻记录就有答案,不用去翻聊天记录。变更日志的真正读者是半年后的自己和接手的人,写的时候按这个标准来。
另外建议CHANGELOG.md和文件内changelog字段并存但职责分开:文件内只保留最近三到五条(方便看 diff 时知道上下文),完整历史放独立的CHANGELOG.md。全部堆在文件头会让每份模板都变得冗长,评审时反而看不清真正的改动。
4. 把"效果变好"换成数字:评测集与回归流水线
这一节是整个体系的承重墙。前面讲的目录、版本号、哈希,都是为了让"比较两个版本"这件事变得可行;而比较的结果,必须落在一组稳定、可复跑的用例上。没有评测,版本化就只是一套漂亮的归档制度。
4.1 评测集怎么攒,攒多少才够
不要一开始就想着攒一个几百条的大集合,会拖到项目结束都攒不完。我的建议是分四层,按优先级依次补:
| 层级 | 规模 | 来源 | 更新频率 |
|---|---|---|---|
| 核心回归集 | 40-80 条 | 需求方确认过的典型场景,每条都有明确期望 | 需求变更时同步 |
| 边界集 | 20-40 条 | 空输入、超长输入、多语言混排、特殊符号 | 每发现一个线上问题补一条 |
| 对抗集 | 15-30 条 | 试图让模型越界、套取约束、改变输出格式的输入 | 每月补充 |
| 真实采样集 | 30-50 条 | 从线上日志脱敏抽样,覆盖长尾分布 | 每两周轮换 |
核心回归集的构建方法是:从需求文档倒推,不要从线上日志正推。日志里高频出现的是常规流量,覆盖不了"必须正确"的关键场景。我通常的做法是拉着需求方一起过一遍业务规则,每条规则至少写一条用例和一个明确的期望判定,这一步花半天,后面能省几十个小时。
边界集的积累全靠线上问题驱动。每出现一次"输入为空导致输出一整段废话"这种问题,就补一条用例,并在用例注释里写上对应的故障单编号。这套机制跑三个月之后,边界集就成了项目最有价值的资产,比任何文档都管用。
真实采样集有个容易被忽视的作用:防止过度拟合回归集。反复针对固定用例调 Prompt,很容易把模板调成"只对这几十条好使",换真实流量就露馅。定期轮换采样集能把这个风险暴露出来。
4.2 指标设计:总分是个陷阱
最省事的指标是一个 0 到 100 的总分,最没用的指标也是一个总分。总分涨了 3 分,你不知道是哪变好了、哪变坏了,也不知道这 3 分是不是在噪声范围内。
实际可用的做法是拆成三组指标:
第一组是硬性合规指标,用确定性规则判定,不依赖模型打分。包括:输出格式是否可被解析(JSON 能不能loads)、必填字段是否齐全、长度是否在区间内、是否包含禁止表述。这组指标必须是 100% 达标,任何一条不过都视为版本不可发布。
第二组是任务质量指标,需要人工或模型辅助判定。包括:关键信息召回、事实一致性、指令遵循度。这组允许有波动,但要对每个具体用例记录"通过/不通过",而不是只算总数,这样回归时能一眼看出是哪些用例从通过变成不通过了。
第三组是稳定性指标,很多人会漏掉。同一个版本、同一条输入,连跑五次,输出的一致率是多少。这个指标在temperature大于 0 的场景下特别重要,因为有些版本的"平均效果"看着不错,但抖动极大,实际落地上线就变成"时好时坏,用户投诉随机出现"。我在一个分类场景里遇到过极端情况:平均准确率 92%,但同一输入五次分类结果出现三种,这种版本宁可不发。
4.3 回归流水线怎么和版本绑定
流水线的原则是"分档触发、结果留档"。
- 提交评审时,跑核心回归集 + 边界集,控制在几分钟内出结果,结果是合并的硬门槛;
- 合并进入主干时,跑全量四层集合,结果写入该版本的验证记录;
- 发布到生产前,再跑一次全量,因为中间可能有模型侧或其他依赖的变化。
关键在于结果要和版本号绑定存档,而不是跑完看一眼就丢。存档内容至少包含:版本号、渲染后哈希、各指标数值、失败用例清单。这份存档在半年后复盘时的价值无可替代——你会无数次需要回答"这个版本当时到底是什么水平"。
流水线里有个实践细节值得说:不要用模型自己给自己打分,至少不要只用这一种方式。用同一个模型评判自己的输出,系统性地偏宽松。更可靠的是"规则判定优先 + 人工抽检 + 必要时双模型交叉",规则能覆盖的部分坚决用规则,规则覆盖不了的部分用小样本人工判定,人工判定的用例集要小而稳定,控制在 30 条以内,保证每次都能认真看完。
5. 上线与回滚:Prompt 的发布动作该长什么样
版本管理做到这一步,很多人会以为告一段落,其实发布环节才是最容易出事的地方。Prompt 的发布不像代码发布有明确的"部署"动作,它经常是"改个配置"就生效了,风险被这种轻量感掩盖了。
5.1 灰度、开关与配置下发的最小实现
不要直接改线上生效的那份模板。最小可行的做法是版本指针 + 分桶灰度:
维护一份映射表,记录"哪个业务场景当前生效哪个版本",代码运行时只读指针,不读具体内容。灰度时给指针加一个分桶规则,比如按用户标识哈希取模,5% 的流量走新版本,其余走旧版本。观察一到两天,指标没有明显劣化再逐档扩大,20%、50%、100%。
分桶键的选择有讲究。用用户标识哈希,保证同一个用户体验一致,避免"刷新一下答案风格就变了";用请求标识哈希,适合那种单次无状态的场景,采样更快但体验会抖。我一般推荐前者,除非流量太小,两天攒不够统计样本。
监控要成对看,不能只看新版。新版的失败率要和同期旧版的失败率对比,因为有些波动是全局的(上游数据变化、流量结构变化),只看新版会误判。我在一个项目里就遇到过:灰度期间新版成功率掉了 2%,正要回滚,发现旧版同期也掉了 2%——是上游某类查询突然变多,跟版本无关。如果没有对照组,这次就白回滚了一次,还会引发不必要的紧张。
5.2 回滚演练和缓存这两个坑
回滚这件事,没演练过的回滚等于没有回滚。我要求每个承接流量的 Prompt 在首次上线前做一次回滚演练:切到新版本,验证指标变化,再切回旧版本,确认指标回到基线、日志里的版本号和哈希正确。整个过程记录下来。演练成本大概十分钟,但能提前发现一堆问题:指针缓存没失效、旧版本文件被误删、下游缓存的键没带版本号,这些在真实故障时发现,代价是几十分钟的线上异常。
缓存是回滚失败的头号原因。两类缓存要分别处理:
第一类是模板内容缓存。服务启动时把模板加载进内存是常规优化,但指针切换后必须能刷新,要有主动失效机制,不能只靠重启。
第二类是输出结果缓存,也就是把相同输入的模型响应存下来复用。这类缓存的键必须包含版本哈希,否则切了版本还在返回旧结果,指标一动不动,你会以为回滚没生效,然后开始乱改。这个坑我踩过,症状是"回滚后指标完全没变,跟没操作一样",排查了半小时才发现是缓存键里只有输入没有版本。
5.3 运行时日志:把"哪一版"写进去
日志字段的设计决定了可追溯性的上限。每次调用至少要落这几个字段:
prompt_id, prompt_version, render_hash, model_id, temperature, top_p, input_tokens, output_tokens, latency_ms, finish_reason, bucket_tagbucket_tag用来标记这次请求命中的是灰度组还是对照组,事后分析时能直接切分对比。finish_reason也很关键,输出被截断和正常结束是两种完全不同的失败模式,但在只看结果的看板上它们可能被混在一起。
这里有个取舍要提醒:完整记录用户输入和模型输出对排查极有帮助,但涉及数据留存和脱敏要求,必须提前和合规侧对齐。我通常的做法是:默认只记哈希和长度,开启调试采样(比如 1%)时才记录完整内容,且采样日志单独存放、定期清理。这样既能定位问题,又不至于把日志系统变成一个没人管的数据池。
6. 团队协作里的那些隐性摩擦
工具和流程搭好之后,剩下的问题基本都在人身上。这一节讲三件在实际协作里最容易卡住的事。
6.1 评审 Prompt 到底该评审什么
用评审代码的方式评审 Prompt,效果很差。代码评审看逻辑正确性,Prompt 评审要看的东西完全不一样。我现在的评审清单固定为四项:
一是变量契约。新增、删除、改名的变量有没有同步到调用方,required标记对不对,默认值合不合理。这一项必须对上代码里的渲染调用点,不能只看模板文件。
二是输出契约。输出格式有没有变,变了有没有通知下游,下游的解析规则跟不跟得上。前面第一幕那个翻车就是漏了这一项。
三是引用变更。includes里的片段版本有没有变,变了之后展开的内容 diff 是什么。评审工具最好能直接展示展开后的完整文本,而不是让人自己去拼。
四是验证证据。这次改动跑了哪些用例,失败了哪些,失败原因是什么。没有验证证据的 Prompt 变更,我的建议是直接打回,哪怕只改了一个字——不是因为一个字有多危险,而是为了让"跑评测"成为肌肉记忆。
这四项之外的东西,比如措辞优不优美、语气自不自然,属于创作者自己的判断空间,不该在评审里争论。评审会变成文风辩论,是最消耗团队耐心的事情之一。
6.2 责任人、废弃标记与定期清理
每份模板必须有owner,而且得是一个具体的人,不能写"算法组"。写组名的结果是没人负责。责任人不需要天天盯着,但版本发布前要确认、废弃时要决策、出问题时要能第一时间找到。
废弃流程要显式化,不能靠删文件。我在第 2 节提过_deprecated目录,配套的做法是给模板加status: deprecated和sunset_date,然后做一次引用扫描:代码里、配置里、其他模板的includes里还有没有引用。全部清干净之后才移入归档目录,保留但不参与加载。
定期清理很重要。模板数量增长的速度远超想象,一个跑了半年的项目攒出五六十份模板很正常,其中大概三分之一是废弃的、重复的或者只在一处用过一次的实验品。我一般每个季度花一个小时扫一遍:三个月内没有任何调用的标记为待废弃,includes里没人引用的片段直接归档。不做这件事的后果是新人进来要面对一片不知道哪些还有效的模板海洋,学习成本陡增。
7. 踩过的坑与落地顺序建议
7.1 高频问题速查
| 症状 | 大概率原因 | 处理方式 |
|---|---|---|
| 版本号一样但输出不同 | 引用的片段升级了,或模型/参数变了 | 比对渲染后哈希与模型标识 |
| 回滚后指标毫无变化 | 结果缓存键未包含版本 | 缓存键加入 render_hash 并主动失效 |
| 评审看不出真实改动 | 只看了原始 diff,没看展开后内容 | 评审工具展示渲染后全文与变量清单 |
| 评测分数很高线上很差 | 回归集过拟合,或采样集长期未轮换 | 轮换真实采样集,增加稳定性指标 |
| 多人同时改冲突 | 缺少 owner 与提交前同步机制 | 明确责任人,小步提交,变更前先跑评测 |
| 排查时找不到当时用的模板 | 日志没记版本和哈希 | 补齐日志字段,历史无法追溯的标注清楚 |
7.2 我建议的落地顺序
如果从零开始,不要一上来就把所有机制铺满,会拖垮节奏。我验证过的顺序是四步:
第一步,先把模板抽成独立文件,带上id、version、owner、variables四个字段。这一步一两天能做完,收益立刻显现——至少改的时候不用在代码里翻。
第二步,建核心回归集,四十条就够,配上规则判定的格式合规检查。这一步大概两三天,但它让后面所有讨论有了共同语言。
第三步,接上渲染层与哈希日志。渲染层负责变量校验、片段展开、内容转义;哈希进日志,让每次调用可追溯。这一步是纯工程活,但它是"可复现"的地基。
第四步,做指针与灰度下发。这是最后一步,因为前面的能力不到位,灰度只会放大混乱。
至于语义化版本的严格判定、变更日志规范、季度清理,这些属于运营层面的事,可以在体系跑起来之后逐步收紧。我在实际操作中的体会是:前两步带来的收益占了整个体系的七成,后两步主要是防止规模变大之后失控。所以别被完整方案吓住,先把模板从代码里拿出来,把四十条用例跑起来,剩下的边跑边补。
最后一个小心得:模板文件的正文尽量写得"可被外行读懂"。半年后来接手的人,可能完全不了解当时的业务背景,如果模板里全是内部缩写和隐晦表述,他改都不敢改。花五分钟在元数据里加一句description说明这个模板干什么用、在哪个环节被调用,这笔投入的回报率高得离谱。