逻辑先行:90%程序员忽略的三大编码铁律
|
去年二月,凌晨三点十七分,机房那台老戴尔的风扇声突然变了调——不是停,是尖啸里夹着咔哒咔哒的敲击感,像有人拿螺丝刀在主板背面刮漆。我抬头看了眼监控屏,nginx 502 刷得正欢,但错误日志里连一条 trace 都没落地。这时候小陈把半杯冷掉的酸梅汤推过来,杯子底还粘着张撕剩一半的外卖单,写着“辣子鸡丁不要葱”。他刚接完电话,手指头还在无意识抠手机壳边沿的裂纹。
文章配图,仅供参考 逻辑先行?我原以为就是写伪代码、画流程图、甩个 UML 给产品看两眼——结果上线第三天,支付回调里一个状态机漏了 reject 分支,用户付了钱,订单卡在“待确认”三十七小时,客服后台手动改数据库改到手抖。这哪是逻辑问题?这是人设崩塌。我们连 if 里套了几个 else if 都没数清,就急着去配 Redis pipeline 的超时时间。可你猜怎么着?压测报告里最刺眼的红点,不是并发扛不住,是某笔退款操作触发了三次库存负扣减——逻辑走歪了,性能再好也是往悬崖上贴金箔。 第一个铁律:函数入口处不校验输入,等于在枪管里装弹前先卸掉保险。上周我扒 openresty 模块的源码,发现他们 parse_json_body() 之后第一行不是读字段,是 assert(ngx_http_lua_check_args)。不是优雅降级,是直接 400。而咱们呢?我翻过三个项目的 /api/v1/order/create,全是先 new Order(),再 try catch 吞异常,最后返回 {code:0,msg:"成功"}——成功个屁,那个手机号传的是 null,MySQL 自动转成空字符串存进来了,三个月后对账对出八千七百单“虚拟用户”。这个我敢打包票:没人在入口做类型+非空+业务语义三重断言,后面全白搭。 第二条更没人提:状态变更必须原子绑定上下文。不是用事务包住就行。去年二月那个崩溃夜,根本原因是我把库存扣减和物流单生成拆成两个独立 HTTP 调用,中间插了个 Kafka。结果 MQ 挂了十七秒,库存扣了,运单没发——下游查库存显示“已售罄”,但订单列表里它还是“待发货”。没人骂 Kafka,都在改前端 loading 动画。可那天我盯着日志发现,扣库存服务里有一行注释写着“// 临时绕过事务,性能要紧”,后面跟着个笑脸 emoji。我真想把那行删了,又怕一删整个集群报警。说句实话,这个我说不准——到底该砍功能保一致性,还是砍一致性保吞吐?问架构师,他正在调试新买的机械键盘,回我:“你先看下 retry 机制跑通没。” 桌上那盒凉透的云吞面,汤已经结了层油膜,飘着两粒紫菜渣。小陈这时候突然笑出声,说刚才运营喊他改 banner,“把‘满299减30’改成‘满299立减30’,说后者显得更果断”。我就看着他鼠标悬停在 CMS 后台,右键点“编辑HTML”,光标在 里闪了十八秒,然后 Ctrl+S。我盯着那个标签,突然意识到——我们连促销文案的语义都靠人工对齐,凭什么指望二十个微服务靠 Swagger 文档保持逻辑对齐? 第三条,也是最扎心的:所有分支判断,必须能映射到真实业务状态机的顶点或边。不能因为“if A return; else if B return; else C return”看起来工整,就当它是完整覆盖。我们组上次重构用户生命周期,把“注销申请中→审核中→已注销→已注销(不可逆)”硬生生压成四个布尔字段加时间戳,结果审计要求追溯“谁在何时批准了哪个环节”,查不出。为什么?因为“已注销(不可逆)”不是数据库里的值,是代码里一行注释:“此处禁止恢复,详见 SOP-2023-07”。这算哪门子逻辑?这是行为艺术。你见过银行核心系统用注释防资金回滚的吗?没有。有也是用状态码锁死的。 其实那天凌晨最吓人的不是告警,是值班群里安静了四分十一秒。王工在老家带娃,发了张孩子攥着奶瓶的照片,背景里电视放着《动物世界》,旁白正念:“豹子捕猎失败,不等于它不会跑。”我盯着那句,突然想起三年前我们砍掉的一个旧模块,叫 order_state_machine_v1.go——当时说“太重”,现在全换成硬编码 switch。但今天早上重启服务后,我重新 pull 了那版代码,发现 v1 里 state.go 文件第 88 行写着:“// 禁止从 cancel_pending 直跳到 shipped —— 违规则 panic”。不是日志,不是提示,是 panic。真狠。 优胜劣汰这事,不是等你发版后让灰度流量替你试错。它发生在我改完一段 SQL 以后,执行 explain 之前;发生在我敲完第一个 test case 断言之后,还没 run 就发现 assert.Equal() 里写的期望值比实际值少了一位;发生在小陈改完 banner 的那一刻,CMS 后台弹窗显示“内容已发布”,但我手机钉钉突然收到测试同学的截图——安卓端按钮文字被截断成“满299立减3……”。我截图发群里,王工回:“截个全屏。” 我截了。他回:“下拉。” 我下拉。他回:“再下拉。” 我下拉到第五屏,终于看见一行小字:“本活动最终解释权归平台所有”。我关掉页面,把云吞面盒子扔进旁边那个印着“绿联 NAS 售后专用”的纸箱里——箱子上还有干掉的蓝墨水印,像是谁签收时蹭的。 我现在每天早上打开编辑器,先把 cursor 放在函数名上,敲 enter,然后空两行,写第一行:// [当前函数承诺达成的、且仅此一项的业务结果]。写完才动键盘。不保证管用。但至少,不会再有人一边喝酸梅汤一边把状态机写成俄罗斯套娃。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


程序员必追:本周编程技术动态与行业快讯
程序员14年感悟:马斯克点破互联网创业三大执念