产品设计

Airbnb:分清预订请求已发送,还是住宿已订好

Airbnb 帮助旅行者寻找和预订住宿。房源可以立即确认,也可能需要房东回应;清楚区分这两条路径,才能知道行程何时真正确定。

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

01
代码思考

为预订请求封装状态转换

假设你负责住宿应用的预订请求页面。按钮和状态卡片需要共用一个小模块,防止用户撤回后又把请求误改成已确认。请实现一个 ReservationRequest(预订请求)模块。

  1. 初始状态与动作: 每个请求从 pending(等待房东回应)开始。apply(event) 接收 accept(房东接受)、decline(房东拒绝)、withdraw(用户撤回)或 expire(到期)。输入保证为这四种事件。是否到期由调用方决定。
  2. 状态规则: pending 收到上述事件,分别转为 confirmed(预订已确认)、declined(已拒绝)、withdrawn(已撤回)或 expired(已到期)。这四种结果都是终态,不再接受后续事件。提供只读状态查询,调用方不能通过改写查询结果改变内部状态。
  3. 返回结果: 成功时返回 {ok:true,state},state 是实际新状态;终态再收到事件时返回 {ok:false,state,reason:"already-final"},表示请求已经结束,原状态保持不变。
  4. 验收与交付: 请求 A 收到 withdraw 后为 withdrawn,再收到 accept 应拒绝且仍为 withdrawn。独立请求 B 收到 accept 后为 confirmed,重复 accept 也拒绝。另一个新请求收到 expire 后为 expired。提交模块、接口说明和这些本地调用的验证结果;不实现计时、付款或页面。
查看思路
  1. 把当前状态放在模块内部,让所有变化经过一个入口,查询只暴露需要的信息。

  2. 将 pending 的允许变化与终态的拒绝规则分开思考,检查返回结果是否同时说明动作结果和实际状态。

  3. 用 A 与 B 的轨迹验证终态不可重开、不同实例互不影响;再检查外部修改不能绕过规则。