产品设计

Libby:暂时不借,也能保留排队位置

Libby 让读者用借书证借阅图书馆的电子书和有声书。遇到热门书需要等待时,可以先预约;暂时没空读,则暂停交付,等准备好后再恢复。

先尝试拆解问题、设计和实现,再展开思路,检查状态、边界与取舍,并设计验证用例。思路提供分析路径,不给出完整实现。

01
代码思考

实现保留暂停位置的等候队列

为图书预约应用实现一个内存中的等候队列。读者可以暂时暂停接收,但恢复后仍应按原来的先后顺序参与下一次分配。

  1. 初始数据: 按加入顺序传入 [{id:"A",paused:true},{id:"B",paused:false},{id:"C",paused:false}]。id 是唯一预约编号,paused 表示是否暂停。模块创建后自行保存队列,不直接改传入数组。
  2. 操作与规则: 提供 setPaused(id, paused),设置仍在队列中的预约并返回设置后的布尔值;传入编号保证存在。它不能改变顺序。提供 takeNext(),移除并返回最靠前且未暂停的预约编号;没有可分配预约时返回 null,队列保持不变。提供 snapshot(),返回按顺序排列的 {id,paused} 副本,调用方修改副本不能改变内部队列。入口名称可以调整。
  3. 验收: 对初始队列调用 takeNext 得到 B;恢复 A 后依次调用 takeNext,得到 A、C、null。另建一个只有暂停的 A 的队列,takeNext 返回 null,快照仍含 A。此时把取得的快照中 A.paused 改为 false,再取一次快照,仍应是 [{id:"A",paused:true}];随后通过 setPaused 恢复 A,takeNext 得到 A。
  4. 交付: 用熟悉的语言实现模块,运行上述两组操作,简短解释怎样同时保住顺序和暂停状态。无需真实账号、页面、网络或过期计时。
查看思路
  1. 先决定如何保存稳定的队列顺序,再把“暂时跳过”表示为预约自身的信息;想一想把暂停者移到末尾会破坏哪个例子。
  2. 明确设置暂停与取出下一项分别负责什么,只有成功分配才移除记录。
  3. 沿两组序列推演,尤其检查全部暂停时没有丢失记录,以及返回快照是否让调用方意外改到内部数据。