一、问题:学习阶梯被抽空了
在日常使用AI的过程中,相信大家对眼前这幅景象很熟悉:把功能需求丢给AI工具,静静看着它实现功能模块,纠正它理解上的偏差,最终达到自己心中满意的效果。代码提交到仓库,后台自动跑集成测试,全部通过。功能成功部署上线,顺顺利利赚了一天工资。
本是一件皆大欢喜的事。对公司来说,功能需求实现并顺利上线了;对我来说,赚了一天工资。
但我总觉得哪里不对劲。结果是好的,但缺少了过程的体验。我觉得自己中间没学到多少东西,没真正理解这个项目,也没经历内心原本看重的那种"啃代码—搞懂—然后动手改"的完整过程。更准确地说:同样的功能,让我不用AI重新实现一遍,我依旧无法独立完成。想到这里就让我难受。
我仔细想了想,到底是哪里出了问题。
回想我以前学编程,是从最低级的错误开始,一个坑一个坑踩过来的。语法写错了,编译器报错;逻辑搞反了,程序跑出莫名其妙的结果;设计考虑不周,上线之后才暴露问题。每一级的坑都在为下一级打地基。
但现在让AI写代码,我发现它几乎不犯低级错误——不会写出空指针,不会搞出死循环。它偶尔出错,但一出就是高级错误,那种你盯着代码看半天觉得每行都对、但就是跑不通的问题。
这意味着什么?学习阶梯的中间几级台阶被抽掉了,你直接站在了高处,脚下是空的。就像在过度无菌的环境中长大的孩子,因为从小没接触过灰尘、细菌这些"小病原体",免疫系统没有经过基础训练,看起来一直很健康,但一旦遇到真正的强力病毒,身体反而不知道怎么反应,比正常孩子病得更重。
更麻烦的是,这些台阶之间是有前后依赖关系的,就像先学加减法才能学乘除法一样。你只有自己踩过"执行顺序搞反导致数据全乱"这种坑,将来遇到多线程并发时才能立刻反应过来——并发的本质就是"你控制不了谁先谁后",知道该往哪个方向查。
如果这些基础的错都没犯过,等遇到更复杂的问题时,你可能连报错信息里的关键词都看不懂,更别说定位问题了。
但这还不是最让我警惕的地方。真正危险的是——你很难意识到自己出了问题。
古人说"知其然而不知其所以然",用在这里再合适不过。AI写的代码,你每一行都读得懂,也看到它能跑通,很容易觉得"我懂了"。但你只是知道它在做什么,并不知道它为什么要这么做。这就像看别人解数学题,每一步推导你都觉得"对,确实是这样",但合上本子自己做,写不出第一步。你以为自己懂了,但那个"懂"是虚的。而最可怕的地方在于,因为代码能跑、测试能过、功能能上线,一切看起来都好,你根本没有机会发现自己其实没懂。
二、应对:重建被抽掉的台阶
意识到问题之后,我开始思考怎么应对。AI不会退场,我也不打算拒绝它,所以解决办法不是"不用AI",而是"换一种方式用AI"。以下是我正在实践和打算实践的几个做法。
让AI出题,而非答题。
在学习新技术的时候,我不再直接让AI写示例代码给我看,而是让它出题给我做。比如我最近在学Redis分布式锁,我会让AI给我一段实现代码,里面故意藏几个会导致死锁的bug,让我自己来诊断和修复。修完之后再让AI点评我的修法对不对,哪里还有隐患。
这么做的意义在于:该踩的坑还是得踩,但AI能让踩坑的过程变得更友好。以前是在野外被蛇咬了才知道这条路有蛇,现在是有人在安全环境里放了一条蛇让你练习怎么应对。经验是一样的,但代价小很多。踩坑不再是被动的、随机的、充满挫败感的,而是主动的、可控的、有节奏的。
拆解任务,一个模块一个模块来。
以前我拿到功能需求,和客户确认完范围和偏好之后,会自己先想一个技术方案,再用AI辅助思考技术选型和架构设计。这个环节没问题。问题出在后面——到了具体编码阶段,方案已经定了,我就把整个实现一口气交给AI了。方案是我的,但代码不是我的,最后我对这个功能的理解停留在设计层面,对代码层面的实现细节是脱节的。
现在我改变了节奏。拆出五个模块,不一次性让AI全写完,而是一个一个来。AI写完一个模块,我先读懂它,遇到说不清为什么要这么写的地方,就追问AI——"这里为什么用这个数据结构?""换一种方案行不行?""什么边界条件下会出问题?"搞清楚之后再进入下一个模块。
这样做的好处是,理解是螺旋式提升的。第一个模块你可能只读懂了表面,但写到第三个模块时你会回过头发现"原来第一个模块那样写是因为要给第三个模块留接口",越往后理解越深,每转一圈你对整体的理解都比上一圈更透。
除了追问"为什么",我还打算从测试用例的角度来加深对每个模块的理解。具体做法是:AI写完一个模块后,我自己先想这个模块应该测哪些场景——正常流程是什么、边界条件有哪些、什么情况下应该报错。同时让AI也独立生成一份测试用例。然后对比两边的差异。差异是双向的——AI覆盖了而我没想到的,是我对这个模块理解的盲区;我想到了而AI没覆盖的,说明我对业务场景的理解比AI更深,这恰恰是AI替代不了我的地方。
"想测试场景"这个过程本身就是在逼自己把"这段代码到底在做什么"想清楚,而且要想得比代码本身更细。如果你写不出有效的测试场景,说明你对这段代码的理解还是表面的。
设"场景",而非设"时间"。
很多人建议"设立无AI时间"——每周留几个小时不用AI,纯手写代码。道理我都懂,但坚持起来真的很难。你一忙起来,这种"额外安排"就是第一个被砍掉的。
后来我换了个思路:不设"时间",设"场景"。也就是说,不额外腾时间,而是在日常工作中挑几个特定场景选择不用AI。
一个场景是修bug的时候。线上出了问题,我先自己诊断,至少把问题定位到哪个模块、什么原因,再去找AI帮忙。修bug本身就是最好的学习机会,因为它逼你读懂代码,而且有现实压力驱动你搞明白,不需要额外的自律。
另一个场景是改动很小的时候。如果只是改个配置、调个参数、加个简单的判断逻辑,自己顺手就写了,不需要启动AI。这些小改动花不了多少时间,但积累起来能保持你对代码的基本手感。
这样做的好处是它不需要你额外腾时间,也不需要靠意志力坚持,而是嵌入到你已有的工作流里。不是"我要专门练基本功",而是"这个场景本来就适合自己来"。
三、写在最后
回到开头那个让我难受的念头——同样的功能,让我不用AI重新实现一遍,我依旧无法独立完成。
现在这个问题还没有完全解决。但我已经不再只是难受了,而是开始做一些改变。拆解模块、追问为什么,这些我已经在做了,能明显感觉到自己对代码的理解比之前更深了——至少不再是"AI写完我提交"这么简单。测试用例的双向对比是我接下来要做的事,效果还在验证中。
我不确定这些方法能不能完全填上那条被抽掉的阶梯,但至少我不再是站在高处脚下悬空的状态了。我在一级一级把台阶补回来。
AI不会退场,我也不打算拒绝它。但我不想只当一个在旁边看着它写代码的人。
夜雨聆风