适合你:会变量、条件、循环和函数,但还不能解释某个框架如何把请求、数据和界面连起来。你不需要先学完 11 个技术栈,也不需要先背完所有 API。
先从总入口选一个模块,打开该模块的 LEARNING_GUIDE.md。它先解释技术在应用中的位置,再给出练习顺序和完成标准。模块 README 保留版本信息和完整目录,查具体语法再进入 reference。
一次只建立一个能运行的练习工程,放在仓库之外,例如与 dev-quest 同级的 dev-quest-labs。每完成一步保存一次代码;不要把不同章节中的多个 main、不同方案的配置或者多个同名组件全拼进一个文件。
第一次实践的产物是一份可重新启动的小工程,以及工程内的 LEARNING.md。开始前确认自己能创建文件、在工程目录运行命令,并用函数接收输入、返回结果;语言语法不熟先从模块导读列出的基础参考补齐。
以待办列表为例,把模块导读中的第一阶段写成下面这份交付约定,再开始读教程:
先核对入口的实际业务和文件边界:basics 中也可能已经包含完整首项目,进入 projects 不代表必须重建工程。下表的“新增标题”是待办示例;书签应按 URL 契约、图书应按 ISBN 与借阅规则、记账应按金额规则验收。以链接正文提供的命令和失败条件为准,不要把另一种业务的字段直接套进去。
| 时机 | 在同一工程中完成的动作 | 证据与下一步 |
|---|---|---|
| 进入 basics | 实现一个固定列表:界面显示一条记录,后端返回一条 JSON,或 CLI 输出一行文字 | 写启动命令、输入和实际输出;启动失败先回本模块环境搭建篇 |
| 遇到 API 不懂 | 查阻塞当前动作的一个条目,例如数组 map、错误返回或查询键,再回原文件改一处输入 |
写“查了什么、它改变了哪个结果”,保存指向参考文章的链接;复制定义不算验证 |
| 进入 projects | 增加新增操作:提交“读一页文档”,再提交三个空格;最后重启工程 | 保存成功写入、空白输入的拒绝结果、重启后记录是否仍在;明确内存、文件或数据库是哪一种存储 |
| 完成本阶段 | 关闭教程,改成“笔记列表”,保留输入校验与读回流程 | 按工程自己的说明重新启动并重复以上动作;通过后选择模块导读的下一阶段,失败则回决定该行为的教程或参考条目 |
如果你选的是非待办路线,可以直接使用下列首项目闭环;每条都先完成模块导读列出的环境与基础语法,产物保存在自己的练习工程中:
| 首项目入口 | 产物与最小验收 | 失败回查与下一步 |
|---|---|---|
| Python 书签 | CLI 工程、锁文件和独立测试数据;新增 URL 后新进程读回,重复 URL 失败,损坏 JSON 保持原样 | 先回正文存储层及“运行与验证”;通过后按 Python 导读 进入 Web 服务 |
| Java 图书 | Main.java 和测试 TSV;新增 ISBN、借出、重新运行查询仍为 BORROWED,未知 ISBN 的 find 非零退出 |
先回正文命令规则与验收矩阵;通过后按 Java 导读 进入 HTTP 映射 |
| 跨平台记账 | 一个已能运行的 Android 或 iOS 工程;0.10 与 0.20 合计 0.30,非法金额被拒绝,重启读回 | 先回正文金额校验、存储与写入失败说明;通过后做该页第二阶段待办与导航,再按 跨平台导读 选择网络练习 |
项目若只有设计片段,把当前产物记为“设计练习”,不要标为运行通过。下一次从 学习进度记录 的最后一条失败证据继续;换技术方向时回 模块入口,无需重走所有模块。
以“读取待办列表”为例,先明确输入是 HTTP 请求,输出是 JSON 或屏幕上的列表。顺着数据走一遍:请求由谁发起、谁检查错误、数据保存在哪里、最后谁展示结果。遇到陌生术语,先用术语解释理解它在这条流程中的作用,再查具体 API。
建议每次完成一个 30–60 分钟的小闭环,时间只是安排参考:
- 预测:运行前写下输入和预期结果。例如新增标题为空的待办,应该显示错误而不是创建空记录。
- 运行:按文档注明的文件、依赖和命令复现。区分“终端退出成功”和“程序行为正确”。
- 改变:只改一个条件,如把正常输入改为空字符串、把存在的 ID 改成不存在的 ID。
- 解释:说明结果在哪个函数、状态分支或数据库约束处被决定。
- 迁移:关掉示例,把“待办”换成“笔记”,独立做一个同类功能。
如果只能复制代码却不能预测第四步的结果,回到较小的示例。不要靠继续读高级章节解决当前概念缺口。
| 标记 | 你需要做什么 | 什么不能据此推断 |
|---|---|---|
| 完整示例 | 按指定文件名保存,安装声明的依赖后运行 | 能运行不代表适合生产使用 |
| 局部片段 | 放入指定已有工程,补齐文档明确列出的上下文 | 单独复制通常不能运行 |
| 反例 | 预测并观察指定失败,随后改回正确写法 | 报错不意味着环境坏了 |
| 设计草图 | 用来理解职责或数据流 | 没给出的函数、数据库和组件不会自动存在 |
旧文章中仍可能有未标注的片段。遇到 ...、TODO、未定义的 service、db、fetchUser,先确认前文是否定义了它。没有定义就把它记录为文档缺口,不要把“补完框架全部知识”当作阅读前提。
| 现象 | 先检查 | 留下什么证据 |
|---|---|---|
| 命令不存在 | 工具是否安装、终端 PATH 是否更新 | 完整命令与版本输出 |
| 找不到模块或包 | 当前目录、依赖安装结果、文件名大小写 | 工作目录、清单和第一条错误 |
| 能编译但结果不对 | 输入、分支、状态归属、返回值 | 最小输入、实际结果、预期结果 |
| 请求一直加载 | 请求是否结束、错误是否被吞、UI 分支顺序 | 状态码、错误对象、渲染分支 |
| 换电脑无法复现 | 运行时版本、锁文件、环境变量、外部服务 | 两台电脑的差异,而非整段截图 |
不要一次升级所有依赖再尝试。先记录模块 README 的基线、自己安装的版本和当前锁文件;只改变一个变量,才知道修复是否有效。
同一句“报错了”可能来自完全不同的层。先把报错归到下表的一类,只读能改变下一步的一篇文章;这比从头重读整个模块有效,也不会把框架配置问题误当成语言基础不足。
| 首条证据 | 常见含义 | 先回哪里 | 做完后要留下什么 |
|---|---|---|---|
SyntaxError、括号/关键字位置错误 |
代码还没有按该语言语法解析 | 共同关键词入口或该语言的基础语法页 | 造成错误的最小两三行与修正后的输出 |
TypeError: ... is not a function、undefined 属性访问 |
导入、返回值、空值或 API 形状与假设不一致 | 当前 API 的 reference 条目;先打印或断点查看真实值 | 调用前的实际值、期望类型和空值/失败分支 |
| 找不到包、构建工具或平台 SDK | 工程目录、锁文件、运行时版本或原生工具链不匹配 | 模块环境搭建篇与 README 的版本基线 | 工作目录、版本输出和第一条完整错误 |
| 请求返回 4xx/5xx 或一直 pending | 输入、认证、服务端约定、网络或取消路径的问题 | 当前项目的请求/错误处理教程;再查 API 契约 | 请求方法、URL、状态码、响应体摘要,避免记录凭据 |
| 代码运行但界面/数据不对 | 状态归属、缓存、持久化或渲染条件不符合预期 | 当前阶段的状态/存储/组件教程 | 一个最小输入、实际与预期输出,以及决定它的状态分支 |
例如,items.map is not a function 先确认 items 的真实值是不是数组,再查 Array.isArray 与 API 返回契约;不要先给项目加状态库。反过来,npm 找不到命令时也不用修改 map 代码。每轮排查只改变一个变量,失败证据保存在工程的 LEARNING.md,下一次从该证据继续。
一节课完成:能解释一个机制,能复现正常情况,能解释一个失败,能独立改出一个变体。
一个模块的入门完成:能从空工程做出小应用,包含输入、验证、状态或存储、输出;能运行一条成功测试和一条失败测试;能说明重启后哪些数据会丢失。
部署完成:在新的环境按步骤启动成功,知道如何检查健康状态、如何恢复上一版以及如何保护配置。应用出现真实用户和复杂故障后,才有条件继续评估可靠性;“生产级”这个标题本身不是证明。
用学习进度记录记录你的证据。文档已经写好与自己已经掌握是两种不同状态。