没有AI的年代,程序员是如何排查Bug的
作者:半吊子全栈工匠2026.11.06 20:53浏览量:0简介:AI编程助手兴起不过数年,在那之前,程序员凭借错误日志阅读、断点调试、日志打印三大基本功定位问题。本文系统梳理这些方法的适用场景与实战要点,补充二分定位、最小复现等进阶技巧,并分析AI时代这些老功夫为何依然不可替代,帮你把排错能力打磨得更扎实。
引言:把时间拨回“没有AI”的日子
智能编程工具的普及也就是近几年的事。十年前的开发者要面对的Bug一个不少,却没有一个能“秒回答案”的助手。前辈们靠什么把问题一个个揪出来?答案并不神秘:一套训练有素的排查方法论,加上日积月累的工程直觉。这套方法论今天依然是工程师的核心竞争力——毕竟,AI定位问题同样需要人提供高质量的输入。下面把这些基本功逐一拆开讲透。
一、错误日志:排错的第一现场
无论什么年代,看到异常的第一反应都应该是读日志,而不是急着改代码。一条完整的错误日志通常包含三类关键信息:
- 异常类型与错误信息:告诉你“发生了什么”;
- 调用堆栈:最顶端的栈帧往往就是出错的代码行,往上翻还能看到完整调用链路;
- 时间戳与上下文:用于和系统其它日志对齐时间线,判断是否伴随其它异常。
面对陌生报错,标准动作是提取其中最具辨识度的句子(剔除与业务相关的变量、路径),拿到搜索引擎和主流技术社区检索,交叉比对多个回答,重点甄别回答者的环境与版本是否与自己一致——同一个报错,版本不同,病因可能完全不同。
有经验的工程师看到熟悉的报错,基本能直接把嫌疑范围缩到某几行代码。这种“一眼定位”的能力,来自长期在报错和根因之间建立映射并持续沉淀。建议维护一份个人“错题本”:报错原文、根因、修复方式、预防手段,几年之后它就是你的私有知识库。
值得一提的是,今天的智能编程工具判断问题,同样以错误日志为第一输入。它的优势是“见多识广”,能很快根据堆栈判断嫌疑代码行,但输入依然是日志——日志写得含糊,AI也只能猜。
二、断点调试:让程序在嫌疑现场“停下来”
看懂报错之后,如果已能大致圈定出错位置,断点调试就是最高效的手段。核心思想是:让程序在预设位置暂停,把运行时的真实状态(变量值、调用链、对象内容)摊开给你看,用“实际值”与“预期值”的偏差锁定问题。
常用操作要点:
- 普通断点:在重点怀疑的代码行上打断点,程序运行到该行即暂停;
- 条件断点:在循环或高频路径中给断点附加条件(如
userId == 123),避免每次命中都停; - 单步执行:逐行观察状态变化,按需决定是否步入函数内部;
- 观察表达式:把关键变量加入监视窗口,暂停时直接与预期对比。
前端的排查思路类似。现代前端工程里,线上代码是编译压缩后的产物,直接读几乎没有可读性。好在构建工具普遍支持生成 Source Map——一份从构建产物回映射到源码的对照表。加载了 Source Map 之后,在浏览器控制台点击报错位置,就能直接跳到源码对应行,断点、单步一气呵成。
断点调试的适用边界也要清楚:它适合“能猜到出错位置”的场景——在怀疑点打断点,没问题就放行到下一个断点,逐段逼近出错行;如果对代码毫无头绪、程序体量又大,满屏打断点反而低效,此时应回到日志和二分法。另外,断点会暂停进程,原则上只适用于开发环境,生产环境不可随意使用。
三、打印日志:最朴素,也最万能
有一种情况是断点调试的死角:异常被 try-catch 捕获后没有做任何处理,程序表面风平浪静,实际上错误被“吞”了。尤其当吞错发生在第三方组件或依赖包内部时,你拿不到源码级上下文,AI工具同样难以凭空判断。看一个典型反例:
try {riskyCall(param);} catch (Exception e) {// 空处理:异常凭空消失}
这类“静默失败”的排查思路是:
- 补全日志:在调用该组件/依赖的所有出入口补打日志,先确认“有没有进、有没有出、出了什么”;
- 核对入参:重点检查传给组件的参数是否符合其契约——类型、取值范围、空值、编码,很多“诡异问题”其实是入参不合规;
- 梳理执行顺序:从入口开始理顺整条调用链,在关键节点补日志,逐段收窄范围,本质是一次手动二分。
改进后的写法应至少保留现场:
try {riskyCall(param);} catch (Exception e) {log.error("riskyCall failed, param={}", param, e);throw new BizException("调用失败,请检查入参", e);}
打印日志看似原始,却是几乎所有环境都通吃的手段:多线程、异步任务、嵌入式设备、生产环境都吃这一套。代价是侵入性强,改一行就要重新构建部署。十年前我做嵌入式开发时对此深有体会:程序要通过U盘拷贝到板子上运行,每加几行日志,就得重新编译、拷贝、上板验证,一轮下来十几分钟。这种“高成本”反而逼出一个好习惯——动手前先想清楚在哪几个关键点打日志,一次到位,而不是撒网式乱打。今天回头看,“先设计日志点位再动手”的思路,正是可观测性理念最朴素的形态。而如今,百度智能云等云平台提供的日志服务、监控告警这类通用能力,已把“看日志”变得高效许多:集中采集、按关键字与时间窗检索、异常自动告警,等于给这门老手艺装上了新引擎。
四、进阶心法:让排查从“凭感觉”变成“有章法”
- 版本二分定位:当问题“以前是好的、最近才坏”时,不必逐个翻提交记录,利用版本管理工具自带的二分定位能力,自动锁定引入问题的那次提交,把排查范围从几十次变更缩到一次。
- 最小可复现场景:把问题从庞大的工程里剥离出来,用最少的代码、数据与步骤稳定复现。复现路径越短,定位越快;一份高质量的最小复现,对自己、对同事、对AI都是最高效的沟通材料。
- 橡皮鸭复述:把代码逻辑一行行讲给“橡皮鸭”(或任何耐心的听众)听,大量Bug会在讲述中自己浮现——因为复述强迫你重新审视每一步假设。
- 警惕环境差异:本地正常、线上出错时,优先怀疑配置、依赖版本、数据规模、网络与时区等因素,而不是先怀疑代码本身。
五、AI时代,老功夫为什么依然值钱
智能编程工具确实改变了调试的节奏:贴上一段报错加上下文,它常能直接指出嫌疑代码行,甚至给出修复方案。但有两个事实值得注意:
其一,AI的输入依然来自人。错误日志、复现步骤、环境信息,这些都要靠人来收集和描述。被吞掉的异常、说不清楚的现象,AI同样无从下手——“喂料”的质量决定产出的质量。
其二,判断仍需人来完成。AI给出的可能是多个候选原因,哪个真正命中,仍要靠你读懂堆栈、看懂变量值、理解业务逻辑来验证,而这些恰恰是读日志、打断点、补日志训练出来的能力。
所以更合理的姿势是“人机协同”:你用传统功夫快速收集高质量现场信息(清晰的报错、最小复现、关键日志),交给智能工具加速推理,再由你验证结论。基本功越扎实,AI在你手里的杠杆越大。
结语
从读日志、打断点、补日志,到二分定位、最小复现,这些诞生于“没有AI年代”的方法论,本质上都在做同一件事:用系统化的手段压缩“从现象到根因”的距离。工具在进化,这个内核不会过时。把它们练扎实,无论未来工具如何变化,你都能在最短的时间内,把任何一个刁钻的Bug按在原地。

登录后可评论,请前往 登录 或 注册