Files
lpt-be/docs/design-review.md
T

147 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 学习进度跟踪系统(LPT)— 架构与设计评审
> 评审日期:2026-07-03
> 评审范围:learning-progress-tracker(后端 Spring Boot + lpt-fe(前端 Vue 3
> 代码基线:feature/review-completion 分支
## 一、整体评价
系统的底层方向是正确的:
- **量化学习投入**(番茄钟 + 学习简报)→ 解决缺乏时间感知
- **优先级排序**(五维度算法)→ 解决缺乏计划性
- **主动回忆式复习**(碎片滚动 + 思维导图对比)→ 解决缺乏复习习惯
三个痛点对应三个解决方案,逻辑链成立。代码质量方面,前后端分离、RESTful API 设计、Flyway 数据库迁移、Sa-Token 鉴权、MyBatis-Plus 多租户拦截等基础设施做得相当规范,超出业余项目的平均水准。
但在**业务设计的心理学层面**,存在几个结构性矛盾:有些地方把"功能完整"等同于"有用",对用户的实际行为模式考虑不足。
---
## 二、不科学之处
### 2.1 番茄钟被当作计时器而非学习节奏工具
当前实现把 25 分钟当作一个硬性倒计时,超时 50 分钟自动暂停,"仅计 25 分钟有效时间"。但番茄钟的核心价值不是"学够 25 分钟",而是**强迫休息—回忆—重置**的节奏。
**问题**
- 允许用户连续学习远超 25 分钟而不触发强制休息提醒
- 超时被视为"违规"(自动暂停),而不是自然的节奏重置
- 后端 session 状态机里没有独立的"休息中"状态
- 前端虽有 5 分钟倒计时但后端无法感知
**改进方向**:番茄钟应该循环——25 分钟学习 → 强制 5 分钟休息并提示填写残片 → 自动进入下一轮。每一轮结束都是自然的"复习锚点"。
### 2.2 优先级五维度权重有重叠,且缺乏解释
| 维度 | 权重 | 问题 |
|------|------|------|
| 主观判断 | 10% | 跟"重要性"、"未来价值"高度相关,用户难以区分 |
| 未来价值 | 10% | 同上 |
| 内容难度 | 20% | 假设"越难越值得优先学"不一定成立 |
| 必要性 | 25% | 与"紧急性"边界模糊 |
| 紧急性 | 35% | 权重最高,但优先级 ≠ 紧迫性 |
核心矛盾:紧急性 + 必要性占 0.60,主观判断 + 未来价值仅占 0.20。系统会自动把"明天要交的报告"排在"你想真正学会的英语"前面——但用户做这个系统是为了后者的。
**改进方向**:两套排序模式——"紧急模式"(按紧迫性)和"重要模式"(按主观+未来价值),用户在不同时间段切换,而不是混合成一个不伦不类的综合分。此外权重应当可配置(当前硬编码在 CalculatedPriorityTool 中)。
### 2.3 学习预期是系统强约束但无闭环
PRD 明确要求"每次学习开始前必须填写学习预期(不可为空)",数据库也建了 study_expectations 表。但:
- 后端没有对应的 Entity / Service / Controller
- 前端 StartTask 页面没有预期输入框
- 预期没有与实际学习报告做任何对比
被强制填写却不被使用的字段,比没有更糟——用户费心填了,却发现系统根本不看。学习预期的价值在于事后对比:"我打算学什么 vs 我实际学了什么",这是元认知训练的核心。
**改进方向**:始于创建 session 时弹窗必填预期,终于结束时展示"预期 vs 实际"对比。
### 2.4 复习模块的认知负荷偏高
当前复习模块有三个独立概念和入口:
- 碎片化提醒(Welcome 页滚动)
- 思维导图上/下载(ReviewDetail
- 回忆对比(ReviewRecall
但用户的真实行为大概是:打开复习页 → 看到滚动条闪过很多内容 → 不知道先看哪个 → 关掉。太多碎片而没有"今天需要复习什么"的引导。
复习行为的心理阻力主要来源于**不知道从哪开始**。
**改进方向**:复习应该"推"给用户一条清晰路径——"你今天有 3 个知识点需要复习,先看第一个"。而不是拉出一个 feed 让用户自己挑。
---
## 三、改进空间
### 3.1 学习报告的长度决策
当前,残片是"休息时记录的内容片段",报告是"结束时生成的完整总结"。但在前端两者几乎无差异——都是文本、都在同一个 feed 中滚动、都在详情页逐行显示。
实际问题:学完 25 分钟后,用户是否真的有动力写一篇"完整报告"?大概率不会——草草写一句"学了线程池"然后开始下一轮。
**改进方向**:降低报告的仪式感。残片应该是主力的学习记录单元,报告改为"自动将本次会话的残片聚合为摘要",用户只需要微调即可。
### 3.2 断点续传的粒度
当前用 pointerPosition(毫秒级指针)支持关闭页面后恢复学习,设计很好。但问题在于:学习结束后,断点续传数据变成死数据。
用户周五回来面对的不是"上次学了什么"的摘要,而是"继续上次倒计时"——但用户可能想重新开始一个关于同一任务的新会话,或者先回顾上次的残片再做决定。
**改进方向**:断点续传配合"上次学习回顾"一起出现——"你上次学了 X、Y、Z,生成了 N 个残片。继续?还是开始新的?"
### 3.3 有效学习时间的 10 分钟阈值
后端逻辑:effective_time < 10 分钟 → 不计入总学习时间,置为 0。
意图是过滤掉"开启后很快就关"的无效学习。但 10 分钟阈值对番茄钟来说太高——25 分钟的 session 如果被电话打断 8 分钟后回来,系统判定"白学了"。
**改进方向**:降低阈值到 3-5 分钟,或改为比例制(有效比 < 30% 才标记低效而不是直接归零)。数据是分析原材料,不是评判工具。
### 3.4 回忆覆盖率的误导性
当前:recall_ratio = matched / (matched + missed)。问题在于它衡量"记得多少节点"而非"记得多少重要节点"。
假如一个任务 100 个节点,其中 3 个核心、97 个细节。
- 用户回忆出 3 个核心 → 覆盖率 3%
- 用户回忆出 97 个细节但漏了 3 个核心 → 覆盖率 97%
显然后者更差,但指标显示前者好。
**改进方向**:节点加权——"应用场景"和"从报告中提取的关键概念"级别更高。或至少同时展示"核心节点覆盖"和"全部节点覆盖"两个指标。
### 3.5 多租户隔离的泛化成本
系统通过 created_by 做租户隔离,每个查询多一个 WHERE 条件、新增数据要注入用户 ID、测试要绕过拦截器。开发笔记中作者自问"这玩应儿除了自己,还能有别人用么"。
多租户本身没有错,但在当前单人使用场景下带来了不必要的复杂度。
**改进方向**:如果未来真有多人需求可还原。当前去掉租户拦截可简化 80% 的查询,减少隐式 bug。
---
## 四、优先级建议
### P0 —— 影响核心使用
- 学习预期的闭环(创建→填写→事后对比)
- 番茄钟循环节律(25分→5分休息 + 自动残片)
### P1 —— 明显改善体验
- 复习引导路径("今天有 N 个知识点需要复习")
- 降低报告仪式感(残片为主、报告自动聚合)
- 优先级权重用户可配置
### P2 —— 优化与完善
- 有效时间阈值下调
- 回忆覆盖率高阶指标(核心节点 vs 全部节点)
- 断点续传配合历史回顾
- 移除不必要的多租户拦截(或标记可选)
---
## 五、总结
系统在基础设施层面(前后端分离、RESTful、Flyway、Sa-Token、MyBatis-Plus)做得相当规范。主要问题不在技术而在设计:**把"功能完整"当成了"有用"**。学习预期无闭环、番茄钟无节奏感、复习无引导路径——这些不需要更多技术投入,而是需要重新理解用户行为。
> 一句话:系统已经可以做很多事情,但用户不一定知道"现在应该做什么"。
> 下一步的改进目标是降低用户决策成本,引导而非开放。