「已授权」背后的谎言:误导性完成态 Flag 让排查多走三条弯路
某次接到运营反馈:「后台显示某用户已完成企微授权,但小程序里看不到他的联系二维码。」
运营的推断链非常自然——「已授权」→「数据应该有」→「一定是小程序渲染出了问题」。于是我们并行开了三条排查链:小程序渲染层、后台数据展示、企微 API 同步。最后发现根子是 Presenter 层的脱敏逻辑,与这三条都没关系。排查多走了约半小时。
现象
后台管理表格有一列「企微授权」,展示逻辑如下:
// 数据库字段
$user->oauth_done = $hasMobile || $hasAvatar ? 1 : 0;// 前端表格列
if (row.oauth_done) { '已授权' } else { '未授权' }某用户 oauth_done = 1,表格显示「已授权」。但他的联系二维码字段 contact_way_qr_code 实际上为空,小程序自然拿不到二维码。
根因
企微的完整授权链路分三步:
- OAuth 回调 — 拿到
mobile/avatar(基础资料) - follow_user 配置 — 企微后台开启「客户联系」
- contact_way 生成 — 调 API 生成带参二维码,写入
contact_way_qr_code
oauth_done 只校验了第 1 步。字段名用了 done,却只代表「有头像或有手机号」,跟「整条链路可用」差了两步。
oauth_done 的命名隐含语义是「OAuth 已完成」,运营和工程师看到这个词,脑子里自动补全的是「整个授权功能可用」。
当功能不可用时,他们第一反应不是「这个 flag 是否准确」,而是「flag 说 OK,那一定是别处坏了」——把排查方向完全引偏。
误导性越强的 flag 名,越能在 bug 现场制造「信任税」,让人把时间浪费在验证那些其实没问题的环节。
正解
按字段的实际语义拆成多个精确布尔列,让「完整可用」成为它们的 AND 组合:
ALTER TABLE wecom_user
ADD COLUMN has_basic_profile TINYINT DEFAULT 0, -- mobile/avatar 任一非空
ADD COLUMN has_followed TINYINT DEFAULT 0, -- follow_user 配置完成
ADD COLUMN has_contact_qr TINYINT DEFAULT 0; -- contact_way_qr_code 非空前端 derive 真正的「完全就绪」状态:
function isFullyReady(row) {
return row.has_basic_profile && row.has_followed && row.has_contact_qr
}后台表格可以进一步细化展示,把三列独立显示,运营一眼看出卡在哪一步。
| 旧命名 | 准确命名 |
|-------|--------|
| oauth_done | has_basic_profile |
| auth_status | oauth_callback_received |
| is_complete | has_contact_qr(具体到步骤)|
has_basic_profile、has_contact_qr 这类名字,第一眼就传达了精确的覆盖范围——它不说「授权完了」,只说「这个具体东西有没有」。
运营看到 has_basic_profile = 1 但功能不可用,第一反应自然是「那二维码生成步骤走了吗?」——直接命中正确链路。
识别误导性 Flag 的三个问题
在给多步骤业务流(OAuth / 入驻 / 上架 / 实名)的「完成态」字段命名前,先问自己:
- 这个 flag = true 时,哪些子步骤可能仍未完成?
- 运营/PM 看到这个名字,会假设哪些功能已经可用?
- 功能不可用时,他们的第一排查方向是否因此走偏?
三个问题里只要有一个答案让你不舒服,就换名字或拆字段。
一句话外卖
xxx_done命名是一张空头支票——它承诺了功能可用,但实现可能只兑现了第一步;把字段名锚定到具体的「有什么」,而不是抽象的「做完了」。