MemoFlow · Goal 模块开发笔记
按版本记录 Goal 从 OKR、记录与任务贡献,到 KR Measurement 和原生工作区的方案。
Goal 模块目标
核心职责:OKR 体系管理、战略层面的进度追踪、长期复盘。
我希望 Goal 不只是一个待办清单,而是用目标和 Key Result 来回答“想达到什么结果”。一个 Goal 可以有多个 KR、起止时间、进度记录和复盘;具体怎么执行,再与 Task 联系起来。
V1.0.0
第一版先采用 OKR 的 Goal + KeyResult 结构。Goal 保存目标名称、时间和整体状态;Key Result 保存具体的衡量指标,用户可以持续追加 GoalRecord 记录进度。
管理方面也想支持文件夹、标签、重要程度和归档,让长期目标多起来以后仍然方便查找。界面准备分成列表、详情、KR 详情和创建表单。创建 Goal 时可以一起添加 KR,后续也允许继续增加。
比较难的是时间和复盘。目标可能只有一个截止月份,也可能没有明确期限;复盘除了文字,还想用 ECharts 对比目标进度与时间进度,看看哪些时段更容易完成任务。这些先作为设计方向,不急着把所有字段都变成固定模型。
v1.1.0
现在要确定 GoalRecord 应该怎样存。记录属于某个 KR,每次提交的数值可能是增量,也可能是一次完整的测量。
关于 DDD 聚合有两种方案:
- GoalRecord 独立为聚合根: 大量记录可以单独查询和写入,但 Goal 当前进度要处理跨聚合的一致性。
- GoalRecord 作为 Goal 内的实体: Goal 和 KR 的约束可以放在同一边界里,更新时更容易一起校验。
按目前设想,单个目标的记录量主要是几百条,不准备只因为“以后可能很多”就提前拆成独立聚合。先让 Goal 拥有 KR 和记录的一致性,再根据实际数据量决定查询、分页与聚合加载方式。
v1.2.0
我希望 Goal 能直接带动每天的行动。一个 KR 可以关联 Task 模板,例如“每周阅读三篇论文”;每次任务实例完成,就尝试给对应 KR 增加记录。
但不能把做完一件事和指标真的变好当成同一回事。固定累加型 KR 可以根据事先约定的规则贡献数值;考试最高分、平均成绩等 KR 则需要真实测量样本。接下来要把 Task 的执行事件与 Goal 的记录权限分开,避免完成任务时直接修改 Goal 数据库。
V2.0.0
这版把 Goal 的职责收敛为 Direction + Measurement。
Key Result 不再只是“当前百分比”,而是有清楚的 Initial / Current / Target。不同 KR 还需要区分记录的计算方式:
- Sum: 本次记录表示正数或负数的变化量,适合“累计学习时长”。
- Max / Min: 每次记录一个实际值,系统保留最高或最低结果,适合“考试最高分”。
- Average: 对样本求平均,不应该把每次输入当成进度增量。
- Last: 以最后一次有效测量表示当前状态。
这里决定由 Goal 独占 KR Measurement 与 GoalRecord 的写入。Task 允许关联 Goal / KR,也可以提交有明确规则的贡献意图,但它没有直接更改 KR 当前值的权限。一次跨模块提交需要可靠传递、幂等处理和来源追踪;Goal 再根据对应的计算规则生成记录。
v2.1.0
模型清楚后,页面和时间语义也需要简化。Goal 的状态先收敛为 Planned、InProgress、Completed、Abandoned;归档单独表示展示和历史管理,不用当作“完成”的另一种状态。
截止时间采用 Day、Month、Quarter、Half-year、Year 等不同精度,保留用户最初选择的粒度。目标日期已经过去,不代表 Goal 应自动进入“任务逾期”状态,也不能自动判定目标失败。
这次还决定移除不属于 Goal 核心能力的目录层级、专注会话和动态 Priority。Task 的执行、Notification 的提醒及 Schedule 的日历展示继续由各自模块负责。
V3.0.0
接下来要让 Goal 的创建、记录和复盘真正围绕用户操作展开,而不只是一组领域对象。
Goal Workspace 可以组合 Goal 自身、KR、Record、Review,以及少量有关的 Task 和 Knowledge 上下文。但这些关联信息只是 只读组合视图,Goal 不因此拥有别的模块的实体。
记录输入也要跟 KR 类型一致:Sum 输入本次变化量,Max / Average 等输入真实测量值;表单应即时展示 Current → After → Target,让用户在保存前看到结果。
AI 可以协助把“备战考试”整理成 Goal、KR 与 Task 草稿,但正常创建、编辑必须仍在 Goal 原生界面确认。数据修改使用聚合版本与权威写入回执,客户端按返回结果更新,不能只依赖嵌套 Store 对象碰巧同步。