U01 · 关掉程序以后,任务还在吗
v0.4 · 自主学习单元。先修:手册 08–12;先完成 工作台。参考选题:Task Tracker。本节题面与代码独立编写。
昨天的准备事项只存在程序的数组里,关闭终端便找不到了。这次做一个自己会用的小命令行工具:记录虚构学习任务,下次启动仍能列出来。先只支持一人、一个进程,不处理多个程序同时写文件。
动手路线:每一步都有文件和结果
先完成 统一启动与恢复手册 的首次准备。以下命令均在自己的练习根目录执行;原文中的 api/web/desktop 概念对应本节列出的现成文件,不需要猜测如何搭空项目。
- 打开
u01/starter/model.ts,按 applyTask → readTasks 的顺序逐个实现。下面第1节起解释规则;每完成一个函数就重跑样例/测试。 - 执行以下三条,分别核对样例、行为和类型。未完成的 TODO 应失败,全部实现后测试应为
fail 0:
node tools/try.mjs u01
node tools/check.mjs u01
npm run check
-
打开
u01/cli.mjs,找到对自己规则函数的调用。先用一句话记录输入从哪里来、结果写到哪里;读不懂的语法回到本节先修对应章节。 -
按下文第4节运行 CLI,不需要数据库或页面构建。
-
实际操作:先添加一条任务,复制真实 id,改为 done,重开终端 list;把文件改坏后读取应失败且文件不变。
-
解释与再做一次:文件不存在与文件损坏为什么不能都返回空数组? 在自己的 LEARNING.md 先写答案,再选本节末尾的变式,列一个新失败例子后修改。保持原用例通过。仅跑通配套界面、没有完成规则与解释,记录为“参考演示已观察”,不记录为自己完成作品。
卡在规则时按“函数输入→分支条件→返回值→参考实现”逐级看提示;卡在运行时按 故障表 定位。若想单独观察参考成品,在构建命令后加 --reference;页面会明确标出参考演示。观察完再去掉该参数重建,继续自己的 starter。
1. 先弄清一次修改会改变什么
打开 u01/starter/model.ts。Task 包含 id、title、status,状态只有 todo、doing、done。编号是身份,标题可以重复。Command 描述一次动作:add/status/delete。动作与资料分开,才能检查“同一份旧资料接到这个请求后应该是什么”。
在 sample.json 看一次 add 请求,预测结果应是编号 a、标题“检查材料”、状态 todo 的数组。执行 node tools/try.mjs u01,初次 TODO 是待实现提示。空数组不是错误,空标题才是。
2. 先完成添加,再改状态
在 applyTask 先处理 add:去除标题两端空白;空标题、超过 60 个 UTF-16 码元、空编号或重复编号都拒绝;返回新数组。不要直接 push 到调用者传进来的数组。把生成随机编号留给外层,测试才可以提供固定编号。
再处理 status:先按 id 查找,不存在就报 NOT_FOUND;存在才生成新的任务对象。delete 也按 id 删除,不能把标题当唯一键。每完成一个分支,执行 node tools/check.mjs u01,看第一组用例覆盖了哪个过程。
观察:一份旧数组经 status 操作后仍是 todo,新结果才是 done。否则页面、撤销或日志都可能读到被悄悄改过的资料。
3. 把文件内容当成待检查的输入
完成 readTasks。JSON.parse 只检查 JSON 语法,不保证顶层是数组,更不保证里面有 id/title/status。先验证数组,再逐项验证字段与重复编号。遇到坏文件抛出错误,不能用 catch 后返回 [];空数组随后被保存会掩盖原有资料损坏。
修改 sample.json 试 [null] 与非法状态,或直接读测试中的例子。正确结果是明确失败。npm run check 检查类型,node tools/check.mjs u01 检查行为;两项分别记录。
4. 运行真正的命令行入口
本包附带 u01/cli.mjs,它调用你写的 starter,并将数据放在自身旁边的 data/tasks.json。先读它的“读文件→应用动作→写临时文件→重命名”顺序,再运行:
node u01/cli.mjs add "检查材料"
node u01/cli.mjs list
复制结果里的实际 id,在 node u01/cli.mjs doing 实际编号 中替换占位文字,再用 done、delete 练另外两个动作。随机编号每次不同,不与书中的固定 a 比较。
重开终端,再 list,应仍读到上次保存的任务。入口只在文件不存在时使用空数组;其他读取错误向上报告。这里的临时写入减少半截文件的机会,但不提供并发锁或完整断电保证。
5. 主动制造一个不会丢数据的故障
停止使用 CLI,在文件管理器复制 data/tasks.json 为个人备份,再把原文件临时改成一个不完整的 {。运行 list,预期失败;再次打开原文件,内容仍是 {,程序没有擅自清空它。恢复备份,再 list。
若看到临时文件已存在,先查看并保存相关文件,确认哪份完整后再移开残留 .tmp。不要把“删掉所有数据再试”写成排错方法。
6. 自检与独立变式
| 操作 | 必须观察到的结果 |
|---|---|
| 连续加两条同标题任务 | id 不同,改其中一项不影响另一项 |
| 使用不存在的编号修改 | 明确失败,原文件不变 |
| 完成后重新启动 | 状态仍为 done |
| 坏 JSON / 重复 id 文件 | 拒绝读取,不静默覆盖 |
独立变式:给 list 增加状态筛选,先说明没有匹配结果时应该输出什么,再改 CLI;保留默认 list 的旧行为。完成 README、Git 差异、坏文件恢复记录后记为本单元自检完成。暂停时保存文件即可,没有常驻服务。
提示顺序:先看命令参数→再看文件实际位置→再看 readTasks→最后看 applyTask。参考在 u01/reference/model.ts,只解释规则,不替代文件实测。下一步可走 U02 或 U11(后者还需笔记先修)。