ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

古法软件开发回忆录:AI时代依然值钱的老手艺

古法软件开发回忆录:AI时代依然值钱的老手艺 1. 为什么我管2022年前的软件开发叫“古法”先说结论我并不是在贬低那个时代恰恰相反我自己的整个技术底子都是在那个“古法”时期打下的。这两年AI编程工具铺天盖地Copilot、ChatGPT、Cursor一路火花带闪电写代码这件事的门槛肉眼可见地往下掉。很多去年才入行的新人对我的第一段工作经历特别好奇——那是一个没有AI补全、没有智能问答、连搜个报错都要靠运气和耐心的时代。我把这段时间称为“古法软件开发”不是因为那时候的人有多苦而是因为那时候的软件开发确实像一门手工活每一行代码都得自己从脑子里长出来每一个报错都得自己顺着堆栈一层层挖下去。2022年是个微妙的年份。不算特别古老但站在今天的视角往回看软件开发的生产方式确实在2022年前后形成了一个清晰的分水岭——AI辅助编程从“玩具”变成了“生产力工具”。在那之前我们的工作流是需求评审、技术方案、建表、写接口、前端联调、自测、提测、修bug、上线。在那之后这套流程依然存在但中间每一环的效率都被AI工具重新冲刷了一遍。那“古法”到底古在哪里核心的差异在于——一切知识获取和问题定位都依赖人本身。你写一行代码之前脑子里得先有一个清晰的模型这个函数会怎么执行、这个对象在内存里怎么布局、这个请求在网络里会走哪条链路。没有AI帮你生成初稿也没有智能工具帮你解释看不懂的报错你必须靠读文档、读源码、读别人项目的代码来一点点构建这个模型。这个“建模”的过程就是古法开发者的基本功。我刚入行的时候带我的师兄有一句话让我印象特别深他说“代码是写给人看的顺便让机器跑一跑。你写不出来一个功能不是手的问题是脑子的模型不够清晰。”那时候不理解后来踩了无数坑才明白——古法开发真正训练人的不是敲键盘的速度而是把复杂问题拆解成简单步骤的能力。而这项能力恰恰是AI时代最稀缺、也最值钱的东西。这篇文章就想好好聊聊2022年之前的软件开发到底是什么样子。我会从工具链、调试方式、协作流程、发布部署这几个维度把那个时代的技术日常拆开揉碎了讲一遍。如果你是这两年才入行的开发者这篇文章能帮你理解“为什么公司里那些老员工总爱说当年如何如何”如果你是和我一样从那个时代走过来的老人这篇就当是一份共同的回忆录——顺带看看哪些老手艺放到今天依然有用。2. 古法工具链编译器、IDE与“等一个构建结果”的下午2.1 从“记事本写代码”说起古法时代的第一个特征是对IDE的选择极其随便——同时也极其固执。我记得2015年前后我的第一台工作电脑是一台ThinkPad E系列4G内存机械硬盘装了Visual Studio之后开机要三分钟。那时候VS已经是重型IDE的代表动辄几个G的安装包打开一个解决方案要加载半天。组里有个前辈更狠他写Python用记事本用命令行跑脚本美其名曰“回归编程的本质”。当时我佩服得五体投地直到后来自己去维护一个老旧的C项目才发现——当你的项目大到一定规模、工具链复杂到一定程度记事本根本撑不住IDE的索引、跳转、重构功能不是锦上添花而是救命稻草。古法开发者的IDE记忆几乎是按语言划分的写Java的逃不开Eclipse和IntelliJ IDEA写C#的基本都在Visual Studio里讨生活写PHP的用Zend Studio或Notepad写前端的早期在Dreamweaver里切图后来才转向Sublime Text、Atom再到VS Code逐渐统一江湖。VS Code是2015年才出的真正大规模普及得等到2018年以后。在此之前前端的日常是Sublime Text打开项目、LiveReload刷新页面、浏览器开发者工具调样式——一套流程行云流水但放到今天看效率低得惊人。IDE的选择直接决定了你的开发体验上限。古法时代有个特别滑稽但也特别真实的现象很多人选IDE不是因为它好用而是因为团队的教程和同事都在用。我第一份工作被要求用Eclipse理由是“公司之前的项目都是Eclipse导出的配置”。结果Eclipse每天崩两次一崩就是“Java heap space”报错我不得不定期去改eclipse.ini里的-Xmx参数把堆内存从256M一路调到1G。现在回想起来那其实是我对JVM内存模型的第一次启蒙——报错报多了自然就懂了。2.2 构建项目等咖啡、刷论坛、看进度条如果说IDE是古法开发的“案板”那构建系统就是案板旁边的“石磨”——慢但是绕不开。Java那边Maven一家独大2012年之前还有不少人用Ant后来Gradle逐渐冒头C/C阵营万年不变地绕着Makefile、CMake转前端则经历了从Grunt到Gulp再到Webpack的进化史。构建的“慢”是古法开发者共同的记忆点。一个中等规模的Java项目mvn clean install全量构建动辄三五分钟要是再跑一轮单元测试十分钟就进去了。前端项目也不遑多让Webpack打包一个大型单页应用早期时要一分多钟改一行代码热更新也要几十秒。所以那个时代的开发者普遍有一个习惯点完构建按钮之后立刻切到浏览器刷论坛、看社区帖子、逛掘金和CSDN——不是摸鱼是真的无事可做。构建跑得慢反而给了人一种“工作节奏感”构建一次看几条技术帖子构建失败回来改代码再来一轮。时间就这么被一块儿一块儿切碎了。现在回头看那个时代的构建系统确实粗粝效率也确实低下但有一件事是今天很多AI工具仍然替代不了的——对构建顺序和依赖关系的直觉。古法开发者都懂Maven的依赖仲裁规则知道两个jar包里同名类冲突是什么感觉知道为什么log4j和slf4j的版本会互掐知道pom.xml里dependency放错位置会导致什么后果。这些知识不是谁教的而是在一次次“为什么我本地能跑、CI上就挂”的疑问中自己摸索出来的。前端那边就更离谱webpack.config.js里一个loader的顺序错了样式就乱了那时候全网都在问同一个问题“为什么我的loader顺序经常出问题”2.3 环境配置“配环境”是一门玄学古法开发最磨人的环节除了构建就是配环境。这个词放到今天依然活跃在各大论坛但2022年前的配环境难度跟现在完全不在一个量级。因为那时候没有Docker没有一键开发容器没有远程开发环境环境问题全靠手工解决。我自己的血泪史就是从JDK开始的。刚学Java的时候配环境变量JAVA_HOME、Path、CLASSPATH这三兄弟就折腾了我整整一个下午。那时候的教程普遍是“照着做”没人仔细讲Path里加了什么、为什么System32目录要放在最前面、为什么Java的bin目录要单独配一条。等到后来学Python又轮到PATH、PYTHONPATH、pip路径这些问题轮番上阵。再往后做Nodenpm的全局安装目录问题、node-sass编译失败问题、Windows下Python 2和Python 3共存问题——每一个都是能让人卡一下午的坑。嵌入式开发那边的环境配置更是地狱级。热词里有个“嵌入式软件开发”这块我虽然做得不多但也帮同事踩过好几次坑。交叉编译工具链的安装、调试器与烧录器的驱动、串口工具的波特率设置、开发板与电脑的连接方式——全是手工活。装错了交叉编译器版本编译出来的二进制文件直接跑不到板子上串口驱动没装好日志永远是一条空白还有那个经典的“回车换行”问题Windows下发的换行符是\r\n嵌入式端只认\n整个串口输出全乱掉。这些坑放到今天一个QEMU虚拟机加一个GCC交叉编译容器就全解决了可在古法时期每一项都是需要靠经验积累才能绕开的坎。2.4 版本控制从SVN到Git的进化版本控制的演化史是理解古法开发的重要线索。我2014年入职的时候公司还在用SVN切换分支得整个目录复制一份合并代码靠人工比对冲突解决更是看命。到了2016年之后Git才开始大规模进入企业——GitHub是2008年上线的但中国互联网企业全面拥抱Git的时间点普遍在2015年以后中大型公司从SVN迁Git往往还要再拖一两年。古法Git时代的“上古操作”放在今天简直不敢想。比如提交信息里写着“update”“fix”“final”一个commit包含了几十个文件的改动改了什么都得靠git diff自己猜再比如很多人不知道该不该把IDE的配置文件加入.gitignore于是每次拉代码都会爆发一场“为什么你的Eclipse配置把我的环境搞坏了”的战争还有一些团队干脆用“copy一份目录当备份”这种原始方式管理代码——我见过某个外包项目的代码目录叫“项目_final_真的final_最终版”光看名字就让人崩溃。那时候团队协作靠的不是工具约束而是自觉和规范文档。组长会反复强调提交信息要写清楚、分支要规范、不要乱pull --force但执行起来全靠自觉。现在回想起来那时期最大的代价不是效率低下而是很多本来可以通过工具避免的人为错误——比如有人把数据库密码提交到GitHub仓库、有人把node_modules一起提交了、有人一个git reset --hard把别人两天的代码冲掉——这些事在古法时代几乎每个团队都发生过。3. 古法调试学断点、日志、搜索引擎与那些“灵异问题”3.1 不会用断点的程序员不是好程序员古法开发的调试方式现在看有一种“手工作坊”的美感打开IDE在可疑的那一行打上断点点Debug按钮程序跑起来停在断点上然后一行一行往下看变量的值。这是那个时代排查问题最主流的路径。但断点调试这个技能在古法开发者之间的评价却是两极分化的——有人视若珍宝有人说那是“浪费时间的活动”远不如在关键节点打日志来得实在。我属于“日志派”和“断点派”的杂合体。本地能跑起来的问题断点调试确实高效特别是遇到复杂的条件分支、循环嵌套、递归调用的时候断点能让你看到每一层调用的真实状态。但有一个场景断点完全没用——线上问题。你总不能在生产服务器上开一个调试端口然后坐着等那个偶现的bug再次触发吧。所以在古法时代线上问题的排查几乎完全依赖日志。日志文化的精髓在于代码里埋的日志点是否足够多、日志级别是否合理、关键路径上有没有打印关键变量。我见过一个运维出身的同事他写代码的日志比业务逻辑还多每个方法的入口、出口、异常分支全部打日志线上出问题直接翻日志就能定位到具体哪一行。当时大家都嫌他啰嗦直到有一次一个线上bug精确到某条SQL的某个参数不对别人还在懵圈的时候他已经从日志里翻出了那个参数的值直接指认了问题代码——那次之后我们组所有人都养成了“关键分支打日志”的习惯。3.2 搜索引擎答疑的黄金时代2022年前Stack Overflow是全球开发者的共同记忆CSDN、博客园、知乎则是中文开发者的老巢。那个时代的技术学习路径几乎是固定的报错复制报错信息到搜索引擎 → 翻前几条结果 → 找一个看起来靠谱的答案复制粘贴 → 跑一下试试。这套流程说白了就是“搜了再用”跟今天“AI直接回答还带解释”的体验差距巨大但恰恰是这套流程培养了我们一项重要的能力——用关键词描述问题的能力。经常遇到的情况是你都不知道自己遇到的是什么问题更不知道应该搜什么关键词。举个例子前端页面在IE6下白屏你连“白屏”这两个字都是乱猜的更别提什么“兼容性”“doctype”“hasLayout”这些专业术语。你得先自己摸索把问题缩小到一个可描述的范围才能搜到有价值的答案。搜索引擎用的是“关键词匹配”不是语义理解你得知道“这个问题的本质是什么”才能问对问题。这个“问对问题”的习惯放在今天是AI时代依然重要——你给AI的描述越好答案质量越高。古法搜索还有一个特点中文社区的答案质量参差不齐有时搜半天搜出来的答案全是错的。我记得有一次遇到一个Oracle数据库的连接字符串问题搜索出来的中文博文全是复制粘贴又互相矛盾的最后在Stack Overflow上一个2011年的老帖子里找到了答案。所以古法开发者都养成了“多语种搜索”的习惯——中文搜不到换英文搜换日文搜甚至直接去看官方文档和源码里面的注释。3.3 “在我机器上是好的”——古法玄学问题实录古法开发最让人头秃的一类问题是那些“玄学问题”明明逻辑没问题、代码没报错但就是运行结果不对。这类问题在2022年前的高发频率比现在高得多。究其原因是那个时代的运行环境、依赖管理、字符编码、系统差异都太不可控了。字符编码问题绝对是古法开发者共同的噩梦TOP 1。早期系统很多是GBK编码后来的新项目一群新人都用UTF-8两边一对接中文乱码是常态。乱码问题的排查路径特别折磨人有可能是数据库表的字符集不对、有可能是HTTP响应头里没指定charset、有可能是Linux服务器默认locale是POSIX、有可能是IDE保存时自动转码了——每一个环节都可能出问题。我记得有一次帮同事排查一个文件上传后文件名乱码的问题最后定位到是Tomcat的URIEncoding默认值是ISO-8859-1不改成UTF-8就必乱。这种问题放现在spring boot 默认UTF-8的体系里已经很少见了但古法时期几乎每个月都能遇到。比编码更玄的是各种“环境差异”导致的问题Windows下路径分隔符是反斜杠、Linux下是正斜杠一个硬编码的文件路径就足以让代码跨平台崩溃时区不对导致的时间偏移八小时是另一个经典还有那个著名的“空格问题”——文件名带空格、路径带空格、命令行参数带空格任何一个都能让脚本毫无征兆地暴毙。最可笑的是这类问题常常要用一种特殊的方式才能复现只有在你赶着上线、心态最崩的时候它才会出现。3.4 从报错到结论一条完整的古法排查链路古法时代的bug排查不像现在AI能直接给答案每一步都得靠人肉执行。我以我自己经历的一个经典线上故障为例子完整走一遍那个时代的排查链路。某次线上系统在每天凌晨3点左右会偶发“连接池超时”报错。日志里能看到报错但不知道是哪个服务的问题。排查流程是先看应用日志的线程栈发现卡在获取数据库连接的环节再看数据库连接池监控发现当时连接数被打满了再看SQL慢查询日志发现有一条SQL在3点整附近执行时间特别长最后定位到是一个定时任务在3点启动全表扫描了一张大表把连接池拖爆了。这个排查过程整整花了两天。第一天在看日志、查监控、压测复现中度过第二天才通过多数据源分析把嫌疑锁定到那条SQL上。放到今天你完全可以写个脚本直接扫描全链路日志找锚点或者让AI帮你分析线程栈。但古法时期整个排查链路依赖的全是命令行工具和日志文件grep、awk、tail -f、jstack、top、sar、binlog。每一个工具都得熟练每一步排查都要有清晰的假设再通过数据去验证假设。这套方法论——提出假设、收集证据、验证或推翻——至今依然是我看家级别的能力。4. 古法交付链路提交代码、凌晨上线与“消防员”时刻4.1 从提测到上线一个古法版本的完整旅程古法软件的交付不像现在这样“CI/CD一条龙灰度发布”现代化拉满。一个版本从代码写到上线要经历一套繁琐程度堪比纸质盖章的流程开发在本地跑通用例 → 提交代码到分支 → 自己打包部署到测试环境 → 喊测试同学验证 → 修bug → 再验证 → 回归通过 → 发上线申请单 → 等待审批 → 在预定的大半夜上线窗口执行发布。那个时代的“测试环境”和“生产环境”差异大得会让你怀疑人生。测试环境是团队共用的一台服务器配置低、数据脏、环境变量东拼西凑生产环境则是完全隔离的独立集群网络策略、端口映射、中间件配置都跟测试环境不是一回事。所以在测试环境跑的明明好好的功能一上生产就莫名的报错排查半天发现是生产环境某个配置文件少了一段Nginx的location规则。这类“环境差异类”问题几乎是每个古法开发者的必修课。上线的过程更是一场体力活。没有现在那种方便的流水线发布基本靠脚本和人工操作先备份当前生产包然后把构建好的新包传到服务器解压、停旧进程、起新进程、检查启动日志、确认服务正常。整套流程少则半小时多则一个钟。如果遇到多节点集群还得一台一台地操作中途任何一步失误都可能造成线上故障。所以那个时代有个不成文的规矩——发布当天是“消防员日”的预备役一不小心就要半夜起来救火。4.2 数据库变更手动执行SQL与“没有回滚”的恐惧古法时代最刺激的环节数据库变更绝对排前三。现在大家习惯了用Flyway、Liquibase这类工具做schema版本管理但2022年以前很多公司的数据库变更还停留在“把SQL写进上线文档由DBA人工执行”的阶段。DBA执行前会问一句“确认没问题吗”你说“确认”他就在生产库上敲下去——至于执行后能不能回退全靠你在开发环境验证得够不够充分。我有一次被数据库变更坑得很惨一张表加索引SQL语句没问题但那张表有上千万行数据执行的时候把数据库锁了一段时间直接拖垮了线上接口。那次以后我养成了一个习惯——任何数据库变更都要先看执行计划评估影响行数和锁范围。这不算什么高深的技术但在当时的团队里很多人根本没这个意识“加个索引而已”然后直接把整个系统干挂的案例在古法时代比比皆是。数据库的回滚更是重灾区很多SQL语句执行完并没有对应的回滚SQL一旦出错只能靠二进制日志手工恢复数据难度极大——所以我后来带团队时强制要求所有上线SQL必须附带回滚方案。4.3 版本管理与灰度策略摸着石头过河古法时代的版本管理思路和今天有巨大差异。现在的发布流行灰度发先放1%流量没问题再放5%、20%、50%最后全量。但在2022年前很多公司压根儿没有灰度系统上线就是一刀切——新版本部署好所有人立刻切到新版。一旦新版有隐藏bug要么马上回滚要么在线上热修补丁。我记得2017年有一次上线移动端App的配套后端接口新版接口做了很大改动但没有留旧版兼容。上线一小时后用户大量反馈首页白屏运维紧急回滚到上一个版本包但由于数据库schema已经被新迁移脚本改掉了旧版代码无法正常运行最后只能连夜写兼容脚本手动修复数据。那是我职业生涯中最漫长的一个晚上。事后复盘时组长只说了一句话“以后任何上线先想好怎么回滚。”这句话我记到今天。灰度发布的思想古法时代就有了但落地方式非常简单粗暴上线时间选在凌晨低峰期发布后先观察一段时间日志和监控指标用F5或Nginx的upstream权重做流量的粗略切换。所谓“灰度”就是两台机器先更新一台、跑一阵子没问题再更新另一台。今天大家所熟知的K8s无损发布、金丝雀发布、AB测试体系本质上都是从古法时代这些朴素操作中进化出来的。4.4 运维与开发的爱恨情仇古法时代的开发和运维关系常常不是“DevOps”而是“Dev VS Ops”。开发怨运维环境总有问题不给开权限不配合调配置运维怨开发乱改配置、不按流程走、出了事就甩锅给运维。我印象最深的是有一次一个同事为了绕过运维的网络策略自己写了个端口映射结果把生产服务器的防火墙规则搞乱了运维连夜封禁了一大堆IP来“止血”第二天开会整整开了一个上午来划责。这种撕裂感在2022年后迅速弱化。Docker容器和编排工具把“环境一致性”这个千古难题解决了大半CI/CD的普及则让开发和运维在一条流水线里各司其职。但古法时期的教训仍然适用开发和运维之间那道墙拆得越早团队效率越高。今天你也许不会手动部署了但如果你不懂线上架构、不懂网络策略、不懂故障恢复那在关键时候依然会抓瞎。5. 古法遗产AI时代里仍然值得保留的老手艺5.1 读报错信息的能力AI时代最容易被忽略的恰恰是古法开发最基础的一项能力——读懂报错信息。现在的AI工具常常直接帮你“解释”报错你甚至不用看堆栈直接把错误代码复制进去就能得到答案。这确实是进步的体现但它带来一个隐患很多人渐渐失去独立分析报错的能力了。古法开发者的报错处理流程是先看错误类型再看堆栈前几行找到出错的文件和行号顺着调用链往上翻猜测可能的原因然后去相关代码处打日志或加断点验证。整个过程完全靠思维逻辑推动没有任何外部辅助。这套方法放到今天依然有效——而且恰恰还是判断一个人技术深度的分水岭。AI能告诉你“这个报错可能是依赖版本冲突”但为什么冲突、冲突的两个jar包是从哪两条依赖链引入的、用exclusion排除哪条才是最优解这仍然需要程序员自己理解依赖图谱才行。5.2 建模与抽象古法时代最值钱的技能AI工具能写代码甚至能设计架构但它无法替代你去理解业务的真实需求。古法时代有个经典说法“编码只占30%70%的时间都在想清楚到底要做什么。”因为没有一个AI帮你快速搭建原型你要在动手之前把各种细节想明白这个模块的边界在哪里哪些数据该归哪个服务管接口的参数怎么设计才能兼顾未来的扩展这些独立思考的过程恰恰是优秀开发者和普通开发者的分水岭。我见过太多新人一上来就让AI生成业务代码生成完了也跑得通但问一句“为什么这里要用消息队列有没有更轻量的方案”就答不上来。这不是他的错而是他的训练环境变了——AI时代默认“能跑就行”而不太关心“为什么这么设计”。古法时代没有AI兜底你设计错了就得自己填坑所以不得不逼着自己去建模、去抽象。这项能力放在哪个时代都不会贬值。5.3 搜索引擎的替代与关键词构建力前边提过古法开发者的“问对问题”能力现在变成了“给AI写对提示词”的能力。本质上这两件事是相通的你需要把你的问题描述得足够准确、足够完整才能在最快时间内获得高质量答案。我见过一些老同事明明对技术细节很熟但给AI的提示词写得语焉不详回答质量就大打折扣反而是公司里几个应届生虽然技术底子薄但特别擅长拆解问题、分步提问拿到的答案质量非常高。这说明什么提示词工程不是新技能它是古法时代“搜索引擎关键词构建力”的延伸。5.4 工程化思维流程、文档与沟通古法开发还有一个常常被人忽略的遗产——工程化思维。那个时代开发要自己处理构建流程、环境差异、发布风险所以每个人都被迫成为“半个运维、半个DBA、半个测试”。这种跨岗位的视角让你更清楚地意识到代码不是写出来就完了还要考虑怎么构建、怎么部署、怎么监控、怎么回滚。现在这些都被工具封装成了“点一下就行”反而让不少新人失去了对整个软件生命周期的完整感知。文档和沟通就更不用说了。古法时代没有AI帮你整理技术方案项目启动会、方案评审会、接口文档、上线记录表全都是手工产出。这些文档写得好不好直接决定了后续开发和维护的顺不顺。我当年带过一个实习生代码写得不错但让他写方案是一塌糊涂。我花了一个多星期教他如何写一份条理清晰的技术方案——先背景、再目标、再现状分析、再方案对比、最后落地方案——这套结构放到今天依然是最通用的表达框架。AI能帮你润色文字、甚至生成初稿但方案里的业务逻辑、技术取舍、风险意识永远是人的活。古法时代的软件开发本质上是一场以人为核心的智力活动。那个时代的开发者用一行行手敲的代码、一个个手工排查的bug、一次次凌晨的上线构建了今天整个现代化软件工程的地基。工具一直在迭代AI也在不断刷新我们对“编程”这件事的认知但那些在古法时代练出来的核心素养——拆解问题、读懂报错、建模抽象、敬畏流程、重视文档——才是穿越周期始终不变的东西。常有人问我如果在今天这个AI加持的时代重新出发还会选择软件行业吗我的答案一直没变会。而且我会庆幸自己在古法时代走过一遭因为那段“慢”岁月让我真正理解了代码只是载体思维方式才是核心竞争力。
返回列表