阅读笔记
-
《代码大全(第2版)》- Steve McConnell
-
《人月神话》- Frederick P. Brooks Jr.
-
《重构:改善既有代码的设计》- Martin Fowler
读后感1:《代码大全》——原来代码不是写出来的,是“养”出来的
“组长,咱们的实验报告代码被助教打回来了,说‘像意大利面一样看不懂’……”上周三晚上,当我收到组员的这条微信时,正瘫在宿舍床上刷短视频。作为小组长,我硬着头皮点开GitHub仓库,看到自己两个月前写的“得意之作”——一个用Python实现的校园食堂排队模拟系统——现在连我自己都看不懂了。变量名全是a1、temp2,函数里塞着200行没注释的循环嵌套,if-else像俄罗斯套娃一样摞了五层。那一刻,我终于理解了《代码大全》里那句警告:“代码首先是给人读的,其次才是给机器执行的。”
从“能跑就行”到“工匠精神”
这本书让我第一次意识到,写代码和写作文其实异曲同工。就像语文老师强调“段落分明、用词准确”,McConnell用整整一章讲变量命名:“别用data这种笼统词,试试unpaidStudentCount!”我翻出上学期数据结构课的作业:一个二叉树的遍历程序里,我竟然把左子树指针变量命名为leftBaby(因为当时觉得“二叉树像一家人”)……现在再看,简直羞耻到想钻地缝。作者说的“代码自文档化”原则,让我在最近的数据库课设里彻底实践:把getData()改名为fetchStudentGradesBySemester()后,连从不写文档的队友都夸“一看就知道这函数干嘛的”。
“防御性编程”救了我的GPA
书里第8章提到的防御性编程,在期中项目答辩时成了我的救命稻草。当时我们组开发了一个选课系统,我在用户输入模块加了大量边界检查:学分上限、时间冲突、课程编号格式……答辩演示时,老师突然说:“我故意输了个‘-3学分’的课程,你们系统怎么没崩溃?”当我淡定地点开错误提示框,展示自动拦截的日志时,他难得地笑了:“不错,有点工程思维了。”后来听说隔壁组因为没处理负数学分,导致数据库出现幽灵课程,被扣了20分。那一刻,我默默给这本书磕了个头。
团队协作的血泪教训
最颠覆认知的是第28章“软件工艺”。以前总觉得代码风格是个人自由,直到小组项目因为混用snake_case和camelCase导致合并冲突频发。后来我们参考书里的建议,用VS Code统一配置了Prettier插件,还约定了“函数不超过屏幕一屏”“禁止魔法数字”等规则。最搞笑的是,我们甚至给项目建了个“代码味道举报墙”——谁发现烂代码就贴便利签,被点名最多的同学要请奶茶。没想到这种沙雕操作反而让项目质量飙升,助教最终点评说:“这是我带过最像正经软件公司的学生组。”
后记:代码是活的
读完这本书,我养成了两个新习惯:一是每天抽10分钟读别人的优秀代码(比如GitHub上的开源项目),二是写代码前先画流程图和伪代码。现在回头看自己大一时写的那些“能跑就行”的代码,终于明白为什么McConnell说:“优秀的程序员不是天生的,是练出来的。”
读后感2:《人月神话》——为什么我们小组越忙越乱?
“咱们组6个人,分3个模块,每人写200行代码,周末就能搞定!”这是本学期软件工程课组队时,我作为组长的豪言壮语。结果一个月后,我们跪在实验室地板上通宵Debug,代码仓库里飘着37个未解决的Issue,而距离DDL只剩12小时。当我读到《人月神话》里那句“向进度落后的项目增加人手,只会让它更落后”时,终于忍不住拍桌大喊:“Brooks你早说啊!”
“人月神话”破灭现场
我们的项目是一个图书馆管理系统,初期计划看似完美:前端2人、后端2人、数据库1人、测试1人。但第二周就出问题了——负责前端登录模块的小王突然退出社团,留下半截代码;临时拉来替补的学妹连Vue都没学过;后端的小张和我在REST API设计上吵了三节课,因为他坚持用GraphQL但没人会写……这时我才懂书里说的“概念完整性”有多重要:一个系统如果缺乏统一设计,就会变成 Frankenstein 式的怪物。最讽刺的是,当我们试图用“人多力量大”解决问题(又拉了2个外援),结果沟通会议从每周1次变成每天1次,时间全花在解释业务逻辑上了。
外科手术团队 vs 菜市场大妈
Brooks提出的“外科手术团队”模型让我醍醐灌顶。回想我们的组队模式,简直就是反面教材:没有明确的主程序员(Chief Programmer),6个人平起平坐导致决策僵局;没有专职文档员,API说明写在草稿纸上还弄丢了;最要命的是,测试同学直到最后一周才发现接口不兼容,因为大家从没同步过进度。相比之下,隔壁宿舍组虽然只有3个人,但明确由有实习经验的学长当“主刀医生”,另外两人分别负责辅助编码和测试,反而提前一周交了作业。这印证了书里的核心观点:效率高的团队不是靠人数堆砌,而是靠角色专业化。
第二系统效应:从极简到失控
我们组还有个致命错误:过度设计。最初需求只是实现图书借阅和归还,但有人提议“加个人脸识别吧!”,有人喊着“要做个微信小程序版”,甚至有人想接ChatGPT实现智能推荐。结果基础功能没做完,反而在边缘需求上疯狂内卷。这完美复刻了书里说的“第二系统效应”——在成功完成一个简单系统后,团队会盲目添加复杂功能导致失控。答辩时老师一针见血:“你们做了100分的炫技功能,但60分的基础功能漏洞百出,这就像给毛坯房装水晶吊灯。”
反思:管理比技术更难
这本书让我深刻认识到,软件工程的核心难点不在技术,而在人与系统的博弈。现在我给所有想当组长的同学三条忠告:1)前期花50%时间做详细设计文档;2)打死不招超过4人;3)每日站会必须控制在15分钟内。虽然我们组最后靠着通宵爆肝勉强拿了B,但下次如果再有人跟我说“加人就能加速”,我一定会把这本书拍在他脸上。
读后感3:《重构》——拯救我那些“过河拆桥”的烂代码
“这段代码是我写的?不可能!绝对不可能!”当我打开半年前的Java课设——一个学生成绩管理系统——试图添加新功能时,发现自己曾经的“杰作”宛如天书:ScoreManager类有1200行代码,calculateRank()方法里嵌套了5层for循环,if (flag == true && b == false || c != null)这样的条件判断像咒语一样遍布全文。那一刻,我无比庆幸自己读了《重构》,否则可能真的要在辞职信中写“因无法理解自己写的代码而退学”了。
第一次闻到“代码臭味”
Martin Fowler在书里列出的22种代码坏味道,几乎能和我课设的每一行代码对应:
- 重复代码:我在
Student和Teacher类里各写了一遍完全相同的validateID()方法; - 过长函数:
exportToExcel()方法长达300行,包含了数据查询、格式转换、文件写入; - 发散式变化:当我试图修改成绩计算规则时,发现要同时改动
ScoreManager、ReportGenerator和TestController三个类……
最搞笑的是,我居然在注释里写过:“这里可能有BUG,但暂时能用,下次再改”——而书里专门批判了这种“用注释掩盖问题”的摆烂行为。
重构实战:从泥潭到乐高
参考书里的“提炼函数”技巧,我把那个噩梦般的calculateRank()拆解成:
getSortedScores()(获取排序后的成绩列表)findStudentPosition()(二分查找学生位置)convertToRank()(处理并列排名逻辑)
每个函数不超过20行,还顺手用Lambda表达式替换了冗长的循环。更惊喜的是,当我用“以多态取代条件表达式”重构了那个满是if-else的getUserType()方法后,代码量从54行缩减到12行,还顺带实现了开闭原则。
测试:重构的安全绳
以前我总觉得单元测试是浪费时间,直到一次重构把calculateAverage()的返回值从四舍五入改成向下取整,导致整个统计模块崩溃。书里强调的“测试覆盖率是重构的前提”让我痛定思痛。现在我会用JUnit给每个核心方法写测试,甚至学会了用Mockito模拟数据库异常。上周重构学生选课模块时,200多个测试用例像安全网一样兜住了所有潜在BUG,这种安全感简直比考试押中题还爽。
重构思维:永不停歇的进化
最大的收获不是具体技巧,而是持续改进的思维习惯。以前交作业的心态是“写完就跑”,现在每次提交代码前都会问自己三个问题:
- 半年后还能看懂吗?
- 如果要加新功能,需要改多少处?
- 如果队友看到这段代码,会骂我脏话吗?
这种心态甚至影响了我的日常生活:整理电脑文件夹时会把“新建文件夹(3)”重命名为“2024_简历_终版_V3”,给女朋友写道歉信时还要分段落加小标题……朋友们都说我“得了重构病”,但我知道,这是成为一个真正工程师的必经之路。