本课问题:哪一层内部证据,能解决我现在还分不清的解释?
前置:已有行为记录;遇到语法时按需查工具箱。
本课交付:一张带证据位置的数据流图,以及明确的停止深挖理由。预计 35–55 分钟。
不要为了“把所有代码都读完”打开文件。先从记录本选一个问题,例如:“C 和 D 在服务重启后为什么不同?”或者“B 保存时,文字有没有离开浏览器?”
源码是一种强有力的证据,但你仍要核对:读的是不是当前运行版本?实际调用是否走到了这条路径?依赖和配置会不会改变行为?
实验页面的“打开恰好需要的一层”能查看当前服务提供的 app.js、lab.py、storage.py。版本号和服务指纹帮助记录条件,不能当作整个系统完整性或身份的密码学证明。
按 F12,打开 Network。清空列表后,只在一个样本保存一条独特文字,观察是否出现与这次保存有关的 POST。
页面初始化和“再读一次”也会发请求,不能看见任何一个请求就断言所有样本都在上传数据。要按时间、路径和请求正文,找到与你刚才操作匹配的那条。
在本实验里,C/D 的保存会出现 /api/notes/实验编号/c 或 /d。查看请求正文中的 text 和 operation;再看响应状态与正文。需要更多 HTTP 背景,可按需查 代码课堂第 02 课。
“没看到请求”目前只说明这次观察没有发现相应请求。开发者工具过滤、已有连接或其他通道可能造成遗漏;接下来读实现,和行为相互核对。
打开 app.js,搜索 saveNote,只追踪当前样本分支:
| 样本 | 在这个实验版本中找到的动作 | 与此前观察的联系 |
|---|---|---|
| A | 给 state.memory 赋新列表 | 新页面重建对象,旧页面状态结束 |
| B | localStorage.setItem 写入特定键 | 同浏览器同来源共享,独立环境不共享 |
| C/D | await api 发起 POST | 数据跨过页面与服务的边界 |
变量名和函数名是路标。初次阅读只需标出输入、分支和保存动作,不必先掌握整个语言。函数与返回值可查 Python 工具箱第 04 课,文件与对象的区别可查 第 05 课。JS 的 localStorage 可参考 代码课堂第 03 课。
打开 lab.py,搜索 do_POST。找到请求正文解析、store.save 调用以及之后发送响应的位置。再打开 storage.py,搜索 Store.save。
对于 C,它把记录加到 self.memory 的列表里。对于 D,它通过参数化 INSERT 写入 SQLite,并在事务上下文正常退出、提交之后返回。
把同一条文字连起来:
输入框的 text
→ app.js 的请求正文
→ lab.py 的 do_POST
→ storage.py 的 Store.save
→ D 的事务提交
→ 服务响应
→ 页面显示确认,再读回列表
源码支持了本实验的具体解释,也说明了“服务回复”和“页面显示”之间还有边界。下一课会故意让这两个边界产生不同结果。
提出一个预测:“如果 D 已提交,再创建一个读取相同数据目录的服务实例,应该仍可读取。”对照第 03 课的重启记录,检查它是否吻合。
另一个预测:“如果只清除 B 对应的存储键,C/D 不应因此消失。”这是可选实验,务必先导出调查报告。不要随手清除整个站点数据,那会同时改变记录本等额外条件。
没有做的实验应标成“待验证”,不能因为代码看起来如此就填写成实际观察。
交付一张不超过七个节点的数据流图,每个关键箭头附上函数名、请求或观察证据。说明哪条假设得到加强,哪条被排除。
然后写清本次停止的位置。例如:“当前只要求服务正常重启后读回,本轮行为与事务代码相符;暂不继续追到 SQLite 的磁盘同步实现。如果用途变为重要长期记录,还需验证备份、异常掉电与恢复。”
能够有理由地停止,也是理解抽象边界的一部分。