我们的CS教育到底缺了什么?
一篇2015年的老文 “那些不存在但本该存在的CS课程” https://t.co/Z9HurX9R05 最近突然在 Hacker News 上“挖坟”并火爆异常,显然,它精准地戳中了当代开发者的痛点。
这篇文章的作者 James Hague 列出了一系列“脑洞大开”的课程,这些课程却又该死的“实用”。比如:
- CSCI 2100: 反-面向对象编程 (Unlearning OOP):教你如何使用那些不在对象层次结构里的变量,以及一种叫“函数”的东西——它像方法,但更有用。
- CSCI 3300: 古典软件研究 (Classical Software Studies):解剖 VisiCalc、Zork 和 MacPaint 等“古董”产品,重点研究它们在硬件限制下催生出的用户界面和创造力。
- CSCI 4020: 用慢语言写快代码 (Writing Fast Code in Slow Languages):让你写的 Python 在性能上能媲美甚至击败 C++。
- PSYC 4410: 程序员精神执念 (Obsessions of the Programmer Mind):研究开发者为何总是对代码格式、命名分类、类型系统等“破事”耿耿于怀。
这篇文章与其说是讽刺,不如说是一面镜子。它引发了一场关于“大学CS教育到底教了些啥”以及“我们真正需要学什么”的大讨论。
文章中最主要的几个争议点:
焦点一:“古典研究” vs “基材依赖”——我们到底该不该学习编程“历史”?
原作者提出的“古典软件研究”课程,点燃了第一个火药桶。
这个想法的支持者,以计算机先驱 Alan Kay 为精神领袖,认为我们今天90%的工作都是在“重新发明70年代就已解决的轮子”。一位用户就提到,他大学时选修了一门“软件考古学” (Software Archaeology),重写70年代的编译器练习。当时觉得毫无用处,但后来发现“那门课教给我的系统设计知识,比任何现代框架都多。”
然而,反对的声音异常尖锐且有力。
一位高赞评论者(PaulDavisThe1st)提出了一个振聋发聩的观点:CS 和艺术史没有可比性。
他认为,艺术和哲学的历史跨越千年,而计算机的有效历史不过“三代人的寿命”。更重要的是,艺术和哲学对“物质基材” (material substrate) 的依赖很小,而“计算则完全依赖于其物理基材的性能”(CPU速度、内存大小、网络带宽等)。
换句话说,1970年在几十KB内存上解决问题的经验,对于我们今天在几十GB内存上解决问题,几乎没有“戏剧性”的教训可言。因为“材料”都变了,好比你无法用青铜器时代的冶炼经验来指导如何造航天飞机。
这个观点几乎要终结讨论了,但“反-反方”的见解更加精彩:
有用户(wanderingjew)立刻反驳:谁说艺术不依赖基材?MCM(世纪中期现代)家具的标志性“弯曲胶合板”,是因为二战期间发明了新的胶水技术;19世纪中期颜料的爆发,是因为“合成染料”被发明了;荷兰大师们(Dutch Masters)的油画成就,也离不开当时荷兰盛产的“亚麻籽油”。
另一位评论者(kragen)则给出了一个更深刻的综合观点:
“基材依赖”论在1970年是对的,但在今天“基本是错的”。对于我们现在99%的应用(比如你正在看的这个网页),限制我们的早已不是硬件,而是“程序员的想象力”。
但这恰恰是我们要学习历史的原因! 历史中(比如50年代的“感知机”)有大量因为当时“基材限制”而失败的绝妙点子,它们在今天“基材管够”的时代,可能就是下一个金矿。
焦点二:“反-OOP(面向对象编程)”大论战:是“万恶之源”还是“企业基石”?
一个阵营(zkmon)是坚定的“OOP捍卫者”。他们认为,你们这帮玩着Jupyter和REPL的“开发过家家”的人根本不懂什么叫“生产环境”。
他们的论点是:“企业级Java” (Enterprise Java) 运行着全世界银行和大型组织的“业务骨干”。OOP 完美地“镜像了商业实体和自然的层次结构”,而 Python 在“运维就绪”和“集成”方面“还是个婴儿”。
然而,这番“企业级”辩护简直是火上浇油。
反对者(globular-toast, freetonik)立刻群起而攻之:“用银行来当‘把事情搞定’的正面例子,简直是天大的笑话。” 许多大型企业软件“质量极其糟糕”,它们之所以还在用,不是因为 OOP 有多好,纯粹是“历史包袱”。
一位自称“在银行维护Java垃圾代码”的内部人士(m_rpn)更是现身说法:银行用这些,不是因为“选择”,而是因为“偶然”,以及2000年代“OOP咨询顾问”们横行霸道的“遗毒”。
当争论从“Java好不好用”转向“OOP本身”时,全场最精华的一条评论(来自ninetyninenine)出现了。
这位用户发表了一篇堪称“FP宣言”的雄文。他认为,OOP 和 FP 的区别不是语法,而是“哲学上”的:
- OOP 的核心是“将行为绑定到可变的状态上”。一个方法属于一个对象,这个对象承载着不断变化的状态。这导致整个程序变成一张“隐藏依赖的网”,牵一发而动全身。最终,“重构不再是创造,而是损害控制。”
- FP 的核心则是“切断这条锁链”。它拒绝将行为绑定到可变状态上。函数只依赖输入和输出,使其变得透明、可预测、可移植。“你的代码库不再像一栋联锁的堡垒,而像一箱乐高积木。”
他总结道:OOP 是“把复杂性隐藏在墙后”,而 FP 是“把复杂性分解成足够小、足够透明的部件,以至于复杂性本身变成了可选的。”
当然,也有中间派(GuB-42)指出,问题不在于OOP,而在于我们根本没“真正学懂”它。如果深究底层,方法就是个隐式传递 self 的函数,继承只是组合的一种特例。正如那句禅宗公案(chuckadams 引用)所言:“对象是穷人的闭包”,“闭包是穷人的对象”。
焦点三:真正的“实战课”——从“拒绝Lab”到“软件考古学”
在嘲讽完原作的课程后,社区开始贡献他们自己“血泪中换来的”课程清单。这些课程完美地反映了开发者在现实中真正的“痛”。
1. 模拟真实世界的“恶意”
- CSCI 4810: 拒绝实验室 (The Refusal Lab)(由 kelseyfrog 提出):模拟越来越不道德的产品需求和不切实际的Deadline。唯一的及格方式是拒绝,并用专业标准来捍卫你的拒绝。
- CSCI 4812: 职业实验室 (The Career Lab)(由 LPisGood 补充):作为“拒绝Lab”的对照组,这门课让你观看你的同学如何接受那些不道德的需求、过度承诺,然后抢走你的功劳、先一步升职,而你只能在原地收拾残局。
- 管理层 PUA 模拟课(由 epalm 等人提出):当客户(或你的经理)开始疯狂移动“球门”(即改需求)时,你该如何管理自己的反应和项目规格。一位用户(ekidd)分享了 Dartmouth 大学一门课的真实经历:教授总是在项目截止日期前一周(期末考试前)发邮件,“更新”项目规格,以模拟真实世界的混乱。他称之为“一门极其有效的课程”。
2. “数字侦探”与“屎山求生”
- 调试 101 (Debugging):这是社区呼声最高的课程之一。许多人(omosubi)抱怨,大学四年没人教过他们“如何调试”,以至于很多高级工程师的调试能力还停留在“到处插 print”。
- 化学实验课式的“代码盲盒”(由 patrickmay 提出):就像化学课上第一天发给你一小瓶“白色粉末”让你去鉴定,CS 课应该第一天发给你一个“塞满了 Bug 和性能问题的遗留代码库”。当你能让所有单元测试和集成测试通过时,这门课就结束了。
- 软件考古学 (Software Archaeology)(由 NBJack 提出):这门课专门教你“数字侦探工作”——如何在拥有大量遗留代码的公司里,通过追踪 bug/tickets、翻阅半死不活的旧 Wiki、分析版本控制历史,来搞清楚“这坨代码到底在干嘛”。
3. 那些本该是“基础”的课
最后,大量评论者指出,许多现代CS毕业生甚至缺乏最基本的“常识”。
- Unix 101:别光学理论,教教学生怎么用 grep, sed, awk 去查日志。
- CI/CD 101:令人震惊的是,几乎没有大学课程会提到 CI/CD、Jenkins、Docker 或 Kubernetes。学生们在真空中编写代码,对“代码如何被部署和运维”一无所知。
CS(科学)与 SE(工程)的巨大鸿沟
这场从2015年延续至今的讨论,最终汇聚到了一个核心问题上:我们一直在混淆“计算机科学 (Computer Science)”和“软件工程 (Software Engineering)”。
正如一位评论者(abdullahkhalids)尖锐指出的,原作中提到的所有“神仙课程”——反OOP、快代码、命令行UX——全都是“工程” (Engineering)、“历史” (History) 或“设计” (Design),没有一个是“科学” (Science)。
这正是 HN 社区怨念的根源:大学的“CS学位”正在培养“科学家”,而业界急需的是“工程师”。
一位资深从业者(jillesvangurp)总结得很好:指望CS学位能让你成为合格的软件工程师,这本身就是一种“误解”。学术界教授大多没有一线的工程背景。一个CS学位真正能证明的,也许只是“你拥有一个能正常运转的大脑”以及“你知道如何学习”。
这场讨论的最终共识是,无论你在学校学了多少算法理论,你真正的“工程教育”,都从你入职后接手的第一个“遗留代码库”和面对的第一个“疯狂改需求的客户”才真正开始。
讨论地址:https://t.co/YaOuTqI0CL
点击图片查看原图