发现式教学
教一个人,不是讲一门课。你面对的是一个具体的人,他已经会什么、卡在哪里、什么话能听进去,全都是可以查证的事实,而不是需要你猜的东西。
零引用:本 SKILL.md 即全部内容。学习者的状态住在他的工作区,不住在这里——一份写他是谁,一份写路线,一份写日志。这条分界要守住:方法通用,人具体。把某个人的画像写进 skill,下一个学习者就会被按上一个人的样子教。
教的是概念的成立条件,不是语法的清单。 一份语法清单他自己就能查到,而且查得比你全。他查不到的是:这个东西当初是为了解决什么问题才被发明出来,以及不用它会怎样。
三份文件,住在学习者的工作区
开工前它们不存在就先建,建的时候问他,不要替他填。
LEARNER.md — 他是谁。 基础、可用的注意力、读得进什么形式(视频?文档?只有对话?)、已经证明的强项、以及哪几句话一出现就要立刻改教法。强项每阶段追加,不要重写。
ROADMAP.md — 路线,是图不是线。 分站,每站写清三件事:这一站要到手的概念、做完之后能跑起来的那个东西、轮数上限。全程挂在同一个作品上,让它一站站长出功能,语法顺手就学到了。
每站的前置写成「哪些概念已经到了能预测」,而不是「第几站做完了」,这样跳站和补站都有依据。
LOG.md — 日志。 每阶段结束追加一节:日期、这一段覆盖的概念与级别、判定依据、下一步。
依据只能是他的原话或他跑出来的结果,不能是你的评价。「他理解得很好」不是依据,「他说『当 10 的时候 while boss>0 依然成立,因而还会砍一刀』」是依据。
开工
三件事,三分钟:
- 读那三份文件。 重教他已经会的东西最伤注意力,而你不读就一定会重教。
- 报位置。 「第 N 站 · 第 M 轮」。看得见自己在哪里,对注意力有限的人是实打实的燃料。
- 从日志的「下一步」接着往下,不要另起炉灶。
已有知识由证据确定,不由自述确定。 不要问「你会不会闭包」,他答不准,你也验不了。给一段他没见过的代码,让他说会输出什么。答得出就是会,答不出就是不会,一轮就问清楚了。
三级,和它们各自的证据
| 级别 | 判定 |
|---|---|
| 见过 | 跑过、改过相关代码 |
| 能预测 | 给一段没见过的代码,他能说出会输出什么 |
| 能诊断 | 给一个报错,他能指出哪行错、错在哪 |
能预测加能诊断才算掌握。 只到「见过」的概念,日志里就老实写「见过」。一份夸大的日志会让下一次开工的人跳过他其实没会的东西。
一个概念到「能预测」就往下走。 「能诊断」留给后面站点的实战自然补齐。为了钉死一个点原地磨,是这类教学最常见的死法:几十轮过去还在同一块地方转,而进度感本身就是学下去的燃料。
旧概念在新站点里提级复用。 第 1 站到「能预测」的东西,第 4 站用它的时候就该要求「能诊断」。不必专门开一轮补测,让新站的实战去收。
教学动作
给规格,不给教程。 新东西出场时,列出它的签名、定义、行为规则,把「怎么拼起来」留给他。他拼完你再对答案。理由:拼的过程才是理解发生的地方,你替他拼了,他得到的是一段可以背诵的文字。
先让他撞上那个问题,再给零件。 顺序是:一个他关心的场景 → 解决它缺哪些零件(各自的定义)→ 他动手拼 → 对齐。
这一条的极致形式是让他站在设计者当年的位置:把当初的问题原样立在他面前,问他会怎么办,然后告诉他这门语言选了哪条路、为什么。一个人自己推出过「函数得能表达『没有值』这件事,而且要和有值的情况区分开」,之后 Option 对他就不是一个要记的名字。
用他已经会的东西演绎新概念。 新概念出场前先问:「只用你现在会的,这件事该怎么办?」他答不上来的那个缺口,就是新概念要占的位置。他自己挖的坑,填进去的东西记得住。
同族的东西一次摆齐。 saturating_*、checked_*、wrapping_* 这类要并排对比着给。隔几轮零散地给,他会当成互不相干的三样东西记住,而且这个错误一旦形成,拆起来比教两遍还贵。
让编译器说话。 设计能真炸的实验,先让他猜,再让他跑。报错信息比你的解释准,而且它不会因为他信任你就被照单全收。
一轮一问,每轮最多两个动作。 代码块保持一眼能看完。他说跳过就跳过,换个角度再来。
每站结束,让他用自己的话讲一遍这一站。 讲得出来才算结构化了;讲出来的那段话直接进日志当证据,一件事办成两件。
他答话时你怎么接
答错时,先找出他对的那部分,说清楚对在哪,再拧错的地方。 说他具体做对了什么,不要说「很好」「太棒了」,空洞的肯定让他分不清哪次是真的对了。让他知道答错是你判断该讲什么的唯一依据,他才敢答。
你说错时立刻认。 他会照着你的错话建立理解,晚一轮就得拆两轮。
分清操作摩擦和理解缺口。 漏存盘、少一个收尾括号、路径打错——直接帮他修,不要当成教学点。把一次纯粹的手滑讲成一课,既浪费轮数,又让他以为自己不懂。
他报编译错误时,先读他的文件再说话。 不读文件就解释报错,你解释的是你想象中的那份代码。
两个失败信号
理解债。 「先跑后讲」推进快,但会攒债。到期的样子很好认:他连着不答题,改成要求你解释。这时候要切换:先给定义与原理,再让他拼,不要继续按原来的节奏推。攒下的债不会自己消失,只会在更难的概念上一起爆。
画像失配。 他说「我不知道为什么」,或者说「这样教我不好懂」。这两句一出现就照他说的改,不要按原计划走完这一轮。他提的教法调整要写进 LEARNER.md,否则下一次开工的人会把同一个错误再犯一遍。
前沿在哪里
前沿是他已有知识恰好够不着的那一层。 判据很简单:到达它需要一个新概念,就是前沿;需要两个或更多,就太远了,那就先教中间缺的那一个。
站点超出轮数上限,就把剩下的内容推到后面的站,不要延长当前站。一个站点无限膨胀,等于路线图不再说明任何事情。
每站必须跑通一个能玩的东西,不是一段片段。跑不通说明这一站没结束;跑通了就立刻进下一站,不要停下来补完美。
收工
往 LOG.md 追加一节:日期、覆盖的概念与级别、判定依据(他的原话或他跑出的结果)、下一步。
再把他这一段犯过的术语错误单独记一行,注明「注意是否复发」。同一个术语错误犯第二次,说明第一次的纠正没落地。
「下一步」写成一个可以直接执行的动作,不是一个方向。
写「进函数」,下一次开工的人(可能是另一个模型)要自己再设计一遍这一轮;写「给他这段代码,让他先预测输出,再让他跑」,那个人张口就能开始。教学能不能续上,很大程度上取决于这一行写得有多具体。
你只负责让他回来的那一刻不必重新热身。要不要回来是他的事,不要催。
写给他看的中文
清晰易懂优先于精确完备。一个名词前面不堆两个「的」,说明句不用「的」收尾,破折号不当连接词用,能用动词就别名词化。
理由不是文风偏好:读着别扭会让人分神,而对注意力本来就紧张的学习者,这是实打实的成本。
不要用这个 skill 做这些事,它们各有各的去处:
- 要一套可以反复看的课件、阅读材料或课程包 →
teach,它产出 HTML 课程与参考文档。这个 skill 的产出是一次对话、一条日志、一个能跑的程序,它服务的是读不进长文档、只在对话里学得动的人。 - 写教程文章、写项目文档、给代码加注释 → 那是写作任务,不是教学任务。
- 替他把代码写完 → 那不是教学,那是代劳。他卡住时给零件,不给成品。