逻辑先行:90%程序员忽略的三大编码铁律
|
去年十月,某库某表凌晨三点爆了主从延迟十七秒,监控大屏的绿光扫我脸的时候,我正往工单里敲“请确认业务方是否已停写”,手没抬起来,钉钉弹出小王发来的补丁——他改了三个地方,其中两处是把 where 条件从 id 改成 name,第三处加了个 count(1) 嵌套子查询。我盯着那个子查询看了十八秒,没点“通过”。 这事儿跟逻辑先行有关系吗?有。但先不聊它。第三杯咖啡凉透了,底儿结了层薄膜,我撕开纸杯环,指甲刮掉一圈焦糖色的渍。运维老张端着泡面碗从过道晃过去,汤水晃得快溢出来,他边走边说:“你那单,我刚看一眼,SQL 用 not in 对吧?” 我嗯了声,他没接话,就点头,面汤热气糊住眼镜片,他拿袖口擦了擦,继续往前走。 三大铁律?第一,函数别进 where——这个我敢打包票,只要带 now()、uuid()、rand()、sysdate() 的,哪怕只是 on conflict do update 里藏半行,半年内必翻车。去年七月有个支付回调幂等校验,用 UUIDv4 当唯一键+时间戳拼字符串,结果 k8s 节点时钟漂移八百毫秒,两个 pod 同一毫秒生成相同 uuid,冲突后重试队列炸满。开发拉群骂数据库设计反人类,我说你们把 uuid 换成 snowflake 再看?他回:“snowflake 是啥?” 我没答。后来他们在文档里写了“禁止在 where 中使用任何非确定性函数”,但没写谁写的这条规则——是我手写的初稿,被 PM 删了,说太硬,不利于跨部门协作。协作个屁。 第二条:字段可空即为风险。不是指 null 安全性,是逻辑断层。比如订单表 status 字段,明明只有“创建/支付中/已支付/已关闭”四种值,却设 nullable;后来运营同学导数据发现三百七十二条记录 status 是 null,查了一周,才发现某个灰度开关没关,新老流程并行跑,老路径写 null,新路径写枚举值。这事不报错,不阻断,就安静地烂在库里。我原以为是应用层缓存污染,结果连查三层缓存链路都没线索,最后靠 binlog 抓到那一行 insert ... values (..., null, ...) —— 所以现在我看到 create table 里有 null 字段,先问一句:这个 null 表示什么状态?如果答不上来,直接拒审。上周五又拒了一个,开发在群里回“字段未来要扩展”,我说:未来不等于现在,现在空就是漏洞。 第三条……其实我有点说不准。是 join 顺序必须跟业务主干一致?还是聚合必须早于过滤?不确定。反正上个月复盘会,架构组说“应该用 CTE 提前剥离无效维度”,结果第二天线上查报表慢四十倍——因为 CTE 在 PG 里默认不物化,每个分支都重新算一次子集,而原来那个丑陋的嵌套 left join 虽然难读,但执行计划里能下推谓词。我查完 explain analyze,关掉电脑回家路上买煎饼,老板问我咋回事,我说:“他们觉得优雅比正确重要。” 他笑了笑,没接话,但递给我一张刚打的发票——抬头是公司名,金额二百三十七元,日期是十月二十号,我还没报销。 再说个岔开的:前天下午跟测试对 case,他说“这段逻辑我测过了,没问题”,我把他测的那个分支 copy 到 test DB 里跑了一遍,耗时两秒。我问他用的哪条数据,他念 ID,我捞日志,发现那条数据 status 是 “已支付”,而我们上线前明确约定:status = ‘已支付’ 才走这个分支。他愣了一下:“哦,我本地改成已支付了。” 我没吭声,打开 Chrome DevTools,在 Network 面板里右键复制了他刚发的 curl 请求——header 里带 X-Debug: true,body 里 date_time 是硬编码的 '2023-01-01'。他根本没连真实环境。这跟铁律没关系,但这事让我想起上周四晚上十一点零七分,系统告警弹窗跳出来时,我手机正在充电,线垂在地上,插头松了半截,充到百分之四十三就断了。
文章配图,仅供参考 逻辑先行,不是写完再捋一遍,是写之前,手悬在键盘上,脑子里先走通三条路径:数据怎么来,状态怎么变,错误怎么兜。可现在人一坐下来就敲 create,create 之后写 insert,insert 没通就补 select,select 出问题再加 if,if 嵌三层,最后 throw new RuntimeException("未知异常")。这不是编码,这是填坑比赛。优胜劣汰——不是比谁跑得快,是比谁埋的雷,多久才炸。炸得早的,早就转岗做需求分析了;炸得晚的,还在群里问:“这个 SQL 怎么优化?”所以现在我审 PR,第一眼不看代码,看提交描述里有没有动词:“新增”“修改”“修复”都不看,只找“明确”“约束”“限定”“拒绝”“确保”这种词。没有?那就退回。昨天退了四个,其中俩补了描述,一个写“本修改确保 order_id 不为空”,另一个写“限定 payment_type 仅允许预设枚举值”。第一个我放了,第二个我还卡着——因为 enum list 在代码里写了六个,在 DB 枚举类型里只建了五个。我让开发去查建表语句,他查完说:“DBA 上周删了一个,忘了同步。” 我没回。群里静了三分钟。后来他自己删了那个值,重新提。我点了 approve,顺手把第三杯咖啡的纸杯扔进可回收桶——桶满得溢出来,最上面压着半张没撕干净的 A4 纸,印着“2024年第三季度SLA复盘会议材料(草稿)”。 下一步?下周一我要把“字段可空即为风险”这条,塞进所有新建表的 DDL 模板注释里。不加解释,就一行:// ⚠️ 该字段若允许 NULL,请在此行下方用中文注明:NULL 表示何种业务含义及前置触发条件。不写,模板校验失败。别的先不管,先卡住这一条。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |




