第一章 Hello World
一
二〇二四年七月十五日,星期一,合肥,三十七度。
王志远拖着一个掉了轮子的行李箱,从地铁口钻出来的时候,后背已经湿透了。
他低头看了一眼手机上的导航——"目的地在您右前方 300 米"。他抬起头,顺着箭头的方向望去,看见一栋十二层的写字楼,玻璃幕墙在烈日下反着光,楼顶立着四个大字:"云智科技"。
这是他即将入职的公司。
说"即将",是因为此刻他站在马路对面,腿有点软。
王志远今年二十三岁,刚从一所普通二本的计算机学院毕业。在校成绩中等偏上,算法课拿过班级第三,数据结构课设做了个红黑树的可视化,被老师当着全班面夸过。但他没有任何实习经历——大三的时候投了几家公司,面试都挂在了"你有项目经验吗?"这个问题上。
他的简历上写着"熟悉 Java",其实主要是刷了两百道力扣,会写 Hello World 和一些排序算法。写着"了解数据库",其实只在课程作业里用 MySQL 建过两张表。写着"使用过 Git",其实只会 git add . 和 git push。
投了一百三十七份简历。大厂全部石沉大海,中厂面了两家挂在了二面,最后是这家叫云智科技的创业公司给了他 offer。面试他的是一个微胖的中年程序员,叫赵北辰,让他手写了一道链表反转。他写出来了,而且写得很快,赵北辰点了点头说:"基础还行。"
就是那个点头,让他拿到了这份月薪八千的工作。
现在他站在马路对面,汗水从鬓角流下来,行李箱的轮子卡在路缘石上发出咯吱咯吱的声响。他抹了一把脸上的汗,深吸一口气,拖着箱子过了马路。
走进大楼旋转门的那一刻,冷气扑面而来,他打了个哆嗦。
二
前台是一个扎马尾辫的女孩,穿白衬衫,笑起来眼睛弯弯的,胸牌上写着"林秀秀"。
"你好,请问找哪位?"
"我……我是来报到的。王志远。今天入职。"
他说话的时候手心全是汗,声音也有点发抖。他觉得自己像一个走错教室的学生。
林秀秀低头翻了翻桌上的名单,然后抬起头,冲他笑了一下:"王志远,对吧?欢迎欢迎!你是技术部赵北辰组的?"
他点了点头。
"来,先把行李放这儿,我带你去办手续。"
她从前台绕出来,动作利落地帮他把行李箱推到角落。路过饮水机的时候,她倒了一杯水递给他:"先喝口水,别紧张,咱们公司挺随和的。"
王志远接过杯子,"谢谢"两个字说得很小声。
林秀秀带着他跑了一圈——行政签合同、财务录银行卡、IT 领电脑。每到一个地方,林秀秀都会替他介绍:"这是我们新来的程序员小王!"然后回头朝他笑:"别老低着头,笑一个。"
他就挤出一个笑。圆脸,黑框眼镜,酒窝。看着确实像个好欺负的人。
IT 的同事递给他一台 MacBook Pro,他接过来的时候手抖了一下——这是他第一次用苹果电脑。在学校里他一直用的是一台五千块的联想,风扇一转起来像直升机。
"WiFi 密码在这张纸上。"IT 同事指了指墙上贴的小纸条。
王志远看了一眼纸条,默默记住了,但没好意思当着人家的面掏手机连。
林秀秀把他送到六楼技术部门口的时候说:"你的工位在里面靠窗第三排,赵北辰会安排你。有什么不懂的随时来前台找我。"
"好,谢谢你。"
"客气啥。"她摆了摆手,马尾辫晃了晃,转身走了。
王志远站在技术部的玻璃门前,透过门上的玻璃往里看——几十号人对着屏幕敲代码,有人戴着耳机,有人在白板前比划,有人对着屏幕皱眉头。没有人注意到门口站了个人。
他推开门,走了进去。
三
赵北辰的工位在最里面,靠近窗户。
王志远走过去的时候,注意到他面前摆了两台显示器,一台开着 IDE,密密麻麻的代码;另一台开着 Confluence,正在写什么文档。桌上放着一杯茶、一本翻旧了的《UNIX 编程艺术》,还有一袋拆开的山核桃。
赵北辰抬起头,认出了他。
"来了?坐。"
他指了指旁边一个空工位。王志远小心翼翼地坐下来,把崭新的 MacBook 放在桌上,不知道该打开还是该等指示。
"电脑先配一下环境。"赵北辰从抽屉里翻出一张纸,上面手写了一串步骤,字迹方方正正的。"先装 JDK 17、Maven、IntelliJ,然后把公司的代码仓库克隆下来,跑一下本地构建。这张纸上都有,不懂的先查,查不到再问我。"
"好。"王志远接过那张纸,像接过考试试卷一样郑重。
赵北辰转回去继续写文档,但过了几秒又转过来:"对了,你叫什么来着?"
"王志远。"
"哦。"赵北辰点了点头,好像在回忆什么。"面试的时候链表反转写得不错,思路很清楚。"
王志远没想到他还记得,愣了一下,耳朵有点红:"谢……谢谢。"
赵北辰嘴角微微一动——看不出是笑还是什么别的表情。"先把环境搞定,今天不急。"
旁边一个帅气的年轻人抬起头看了王志远一眼,没打招呼,又低下头去了。胸牌上写着"陈锐"。
王志远打开 MacBook,深吸一口气,开始照着那张纸装环境。
装 JDK 还算顺利——他在学校装过。Maven 也还好,虽然第一次在 Mac 上配 settings.xml,但搜了一下就搞定了。IntelliJ 打开的时候他心里咯噔了一下——社区版还是旗舰版?纸上写的是旗舰版,他没有 license。正犹豫要不要问赵北辰,旁边传来一个声音:
"用公司的 license server,地址在内网 Wiki 上。"
他扭头一看,是一个短发女生,干练利落,眼神有点犀利。胸牌上写着"苏薇"。
"啊,谢谢。"
苏薇没有再理他,继续盯着自己的屏幕。屏幕上是一个 Pull Request 的页面,她正在写 Review 评论,手指在键盘上噼里啪啦地敲,像在打仗。
装好 IDE 之后,最后一步是克隆代码仓库。王志远照着纸上的 Git 地址敲了命令——
git clone git@git.yunzhi.com:backend/order-service.git
权限被拒绝。
他慌了一下,检查了地址没打错,又试了一次,还是不行。他鼓起勇气去问赵北辰。
"SSH 公钥配了没?"赵北辰头也没回。
"……什么公钥?"
赵北辰这次回过头来看了他一眼,表情平和,但王志远感觉自己像裸考被抽到了不会的题。
"在终端里生成一个 SSH 密钥对,把公钥添加到 GitLab 上。纸上没写是我疏忽了。"赵北辰说着从桌上拿了支笔,在纸的空白处补了两行命令。"试试。"
十分钟后,代码克隆成功。下载进度条走到 100% 的那一刻,王志远有一种通关了新手村的感觉。
他打开项目,看着目录树——几十个 module,上千个文件,密密麻麻的包名像一棵看不到顶的大树。他突然觉得自己在学校写的那些课程作业,像是在纸上画的火柴人,而眼前的,是一座真实的城市。
四
真正的灾难发生在下午。
本地构建跑通之后,赵北辰给他指了一个任务——熟悉一下订单模块的代码,试着在本地把服务启动起来,跑一下 API。
"配置文件在 config 目录下,本地用 application-local.yml。"赵北辰说。
王志远点头,打开了 config 目录。里面有好几个配置文件:application.yml、application-dev.yml、application-test.yml、application-local.yml。他看了一眼,觉得都差不多,随手用了默认的 application.yml 来启动——他当时不知道,不同的配置文件连的是不同环境的数据库。
服务启动了,他很高兴。终端里打出了一堆日志,最后一行写着 "Started OrderServiceApplication in 6.3 seconds"。他截了个图发给他妈:"妈,我上班第一天,项目跑起来了。"
他妈回了个竖大拇指的表情。
接下来他想试试接口,赵北辰让他用 Postman 发个请求看看。他对照着接口文档,构造了一个更新订单状态的请求。文档上写的是"根据订单 ID 更新状态",他看了一下参数,照着写了个 SQL 查询——
等等,他没有用 Postman。
事情是这样的:他在翻代码的时候,看到了一个叫 order_status 的数据表。他想看看里面的数据长什么样,就打开了 IDE 自带的数据库客户端,连上了配置文件里的数据库地址。然后他想更新几条测试数据来验证接口。
他写了一条 SQL:
UPDATE order_status SET status = 'PROCESSING';
没有 WHERE 子句。
他按下了回车。
终端返回:"Affected rows: 4,827"
四千八百二十七行。
王志远的脑子空白了两秒钟。他意识到自己没有加 WHERE 条件——所有记录的状态都被他刷成了 'PROCESSING'。
同一时间,公司的钉钉群里炸了。
QA 组的人开始发消息:
"测试环境的订单状态怎么全变了?"
"我刚跑的回归测试全挂了!谁动了数据库?"
"@ 所有人 测试环境异常,紧急排查中。"
王志远盯着屏幕上的 "4827",手开始发抖。他终于想起来——他用的是默认配置文件 application.yml,连的不是本地数据库,而是测试环境的数据库。
他的脸一阵一阵地发白。
陈锐抬起头,看了一眼群消息,又看了一眼王志远的屏幕,嘴角微微一动,没说话。
旁边一个笑嘻嘻的中年程序员——工位上堆满了零食袋,胸牌上写着"马德华"——探头过来看了一眼:"嚯,小伙子,你这是连上测试库了?"
王志远嘴唇哆嗦了一下,说不出话。
"赵哥——"马德华提高了声音,"新来的小朋友好像闯祸了。"
五
赵北辰放下茶杯,走过来。
他看了一眼王志远的屏幕——打开的数据库客户端、那条没有 WHERE 的 UPDATE 语句、Affected rows: 4827。然后他看了一眼钉钉群里 QA 的消息。
"嗯。"他说了一个字。
王志远觉得自己要被开除了。入职第一天,把测试环境搞瘫了。他的脑子里已经开始排演回家的路线——从合肥回小县城,大概两个小时的大巴。他甚至开始想该怎么跟他爸解释。
赵北辰在王志远旁边坐下来,拉过键盘,打开了一个终端窗口。
他先看了一下 application.yml 的数据库连接配置,确认了是测试环境。然后查了测试数据库的备份策略——每天凌晨四点有一次全量备份。他联系了 DBA,确认了备份可用,十五分钟后把数据回滚了。
全程没有发火,没有叹气,甚至没有皱眉头。
QA 群里,赵北辰发了一条消息:
"测试环境数据已回滚,是新同事的误操作,配置文件用错了。给大家添麻烦了,抱歉。"
然后他转过头,看着王志远。
王志远低着头,不敢看他。脖子上的汗比中午在太阳底下走还多。
"抬头。"赵北辰说。
王志远抬起头,嘴唇动了一下,没说出话来。
赵北辰的语气平和,但很认真:"犯错不可怕,入职第一天犯错也不可怕。但你要知道错在哪里。"
他指了指屏幕:"第一,你用了默认配置文件,没有确认它连的是哪个环境。开发环境、测试环境、生产环境,是三个完全不同的世界。你在本地开发,永远用 local 或者 dev 的配置,绝对不要碰 test 和 prod。"
王志远拼命点头。
"第二,你写 SQL 的时候没有加 WHERE。"赵北辰拿过笔,在纸上写了两行:
-- 第一步:先查,确认影响范围
SELECT * FROM order_status WHERE id = 123;
-- 第二步:再改,带上明确的条件
UPDATE order_status SET status = 'PROCESSING' WHERE id = 123;
"动数据库之前,先 SELECT 看一眼,确认连的是哪个库、影响的是哪些数据。这是基本功,今天记住了,以后不会再犯。"
"明白了。"王志远的声音很小,但很认真。
赵北辰拍了拍他的肩膀:"环境配置是工程的第一课。你在学校学的是算法和数据结构,那些是地基。但盖房子不只是地基——怎么配环境,怎么管配置,怎么安全地操作数据库,这些都是工程素养。你之前没接触过,不怪你,但从今天起要补上。"
他起身回了工位,走到一半又回头说了一句:"今天的事不丢人。我刚工作那年,也干过类似的蠢事。"
旁边马德华嘿嘿笑了一声:"赵哥当年可是把生产环境的缓存清了——"
"别提了。"赵北辰打断他,但嘴角动了一下。
六
剩下的下午,王志远一个字都没说。
他重新用 application-local.yml 启动了服务,确认连的是本地数据库。他在纸上把赵北辰写的那两行 SQL 抄了一遍,又抄了一遍。然后他翻遍了项目的 config 目录,把每个配置文件对应的环境都搞清楚了,记在了笔记本上:
application-local.yml→ 本地开发(连本机数据库)application-dev.yml→ 开发环境(共享开发库)application-test.yml→ 测试环境(QA 专用,别碰!)application-prod.yml→ 生产环境(碰了就死!)
他在"碰了就死"后面画了三个感叹号。
下班的时候已经七点了。技术部的人走了大半,赵北辰还在,但看起来是在写自己的技术博客——屏幕上是一个 Markdown 编辑器。
王志远收拾东西的时候经过赵北辰工位,鼓起勇气说:"赵哥,今天……对不起,给大家添麻烦了。"
赵北辰摘下耳机:"道歉有了,但道歉只需要一次。比道歉更重要的是你记住了什么。"
"先 SELECT,再操作。确认环境,再执行。"王志远几乎是脱口而出。
"嗯。"赵北辰点了一下头,这次嘴角的弧度明显一些了。他转回去戴上耳机,又摘下来补了一句:"志远,记住一句话——笨功夫才是真功夫。别想走捷径。"
"明天见。"
王志远走出公司大门的时候,天已经黑了,但暑气还没退。他拖着行李箱——对了,他的行李箱还在前台旁边放着,差点忘了。
他折回去拿箱子的时候,发现林秀秀正在收拾前台。
"嗨,你还没走?"林秀秀看到他,笑了一下。"第一天感觉怎么样?"
王志远想了想,决定实话实说:"我闯祸了。把测试环境的数据库搞坏了。"
"我知道。"林秀秀笑得更开了,"QA 的姐姐们在群里骂了半天,但也没点名。赵哥帮你挡了。"
"嗯……赵哥人挺好的。"
"赵哥是公司里公认的好人。技术最强,脾气最好。"林秀秀递给他一瓶矿泉水——不知道什么时候准备好的。"第一天都会犯错的,别往心里去。明天会更好。"
王志远接过水,说了声谢谢。他拖着行李箱走进夏夜的热浪里,身上的衬衫前后都是汗渍。
回到他租的合租房——政务区一个老小区的次卧,月租一千二,隔壁住着一个外卖骑手——他把行李箱靠墙放好,坐在硬板床上,打开手机。
他爸发来一条微信:"第一天上班怎么样?"
他想了很久,打了一行字:"挺好的,同事们都很好。"
删掉。
又打了一行:"第一天就闯了个祸,但学到了很多。"
删掉。
最后他发了一条:"挺好的,学到了不少东西。爸你放心。"
他爸回了个"好"字,后面跟了一个笑脸。他能想象他爸的样子——坐在客厅的沙发上,戴着老花镜,慢慢地用一根食指戳手机。
王志远放下手机,从背包里翻出一个新买的笔记本,在第一页写下:
Day 1
- 环境分四种:local、dev、test、prod。本地开发只用 local。
- 动数据库之前,先 SELECT 看一眼。
- 赵哥说:环境配置是工程的第一课。
- 前台小姐姐人很好。
他想了想,把第四条划掉了。
又想了想,在旁边画了条线,把它恢复了。
:::{admonition} 小胖的笔记 :class: tip
本章知识卡片:环境配置与数据库安全操作
1. 开发环境的四个层次
| 环境 | 用途 | 谁在用 | 能不能随便动 |
|---|---|---|---|
| local | 本地开发调试 | 你自己 | 随便折腾 |
| dev | 联调开发 | 开发团队 | 可以动,但别太野 |
| test | 集成测试 | QA 团队 | 别碰!改了人家要骂你 |
| prod | 生产环境 | 真实用户 | 碰了就是事故! |
2. 数据库操作的黄金法则
- 先 SELECT,再 UPDATE/DELETE:永远先查一遍,确认影响范围
- 带上 WHERE:没有 WHERE 的 UPDATE 是一颗定时炸弹
- 确认连接:执行任何操作前,先看一眼你连的是哪个库
3. 新人生存第一课
- 配置文件不是摆设,每一行都可能指向不同的世界
- 犯错不可怕,不知道自己错在哪才可怕
- 记笔记。把踩过的坑记下来,同样的坑不踩第二次
:::