这是一组文章的第一篇。整组讲一件事:计算机学科到底在解决什么问题,你手上那些零散的技能,各自站在哪一格。
写这组文章的起因很具体:很多人会装系统、配网络、架服务、写脚本,干得也不错,但你问他「你在计算机学科里属于哪一块」,答不上来,或者答「运维」。「运维」是岗位名,不是学科位置。
判断方法很简单:换一个岗位,你学的那些还在不在? 在,说明你拿到的是学科能力;不在,说明只拿到了操作流程。
一、先看一个错位
假设你现在能独立完成这些事:
- 装系统、分区、配网络、改 DNS
- 用 SSH 连服务器,传文件,配密钥
- 架 nginx,申请证书,把站点跑起来
- 写 shell 脚本,定时任务,看日志找问题
- 装数据库、跑 Docker、做备份
这已经不算差了。但如果只停在这一层,你会有一种说不出的感觉:每件事都会做,但不知道自己在做什么。
这种状态有个诊断标准——换一个场景,你的能力还剩多少。
- 换成维护一套高并发服务,你会的那些还够用吗?
- 换成一个从来没有的性能问题,你知道从哪下手吗?
- 有人说「这个方案太慢」,你能判断是慢在哪一层吗?
答不上来的部分,就是学科知识缺的那部分。
二、学科的定义里藏着一个骨架
《计算机学科概论(第 3 版)》第 26 页给的定义是这样的(这里只引关键半句,其余是我的转述):
计算机学科是对描述和变换信息的算法过程,包括对其理论、分析、设计效率、实现和应用等进行的系统研究。
这句话读快了会滑过去。但注意它列了五个词——理论、分析、设计效率、实现、应用。这不是修辞,这是一条完整的链:
| 这五个词 | 它在问什么 | 大多数人站在哪 |
|---|---|---|
| 理论 | 什么能算,什么根本算不了 | 空白 |
| 分析 | 这个办法好不好,怎么判断 | 空白 |
| 设计效率 | 复杂度,快在哪慢在哪 | 有模糊感觉 |
| 实现 | 写出来、跑起来 | 强 |
| 应用 | 装到机器上给人用 | 强 |
所以问题不是「什么都不会」,是偏科。 而且偏的方向极其一致:上半段(实现、应用)很厚,下半段(理论、分析、设计效率)几乎是空的。
这不需要自责。因为你是从「让机器干活」这条路径进来的——先能跑起来,才有兴趣往下看。但停在实现层,天花板很低,而且自己看不见天花板在哪。
三、一句话把零散知识串起来
同一本书第 31 页讲「学科的根本问题」,这一句我认为是整个学科最值钱的一句话:
计算机学科所有分支领域的根本任务就是进行计算,其根本问题仍然是什么能被(有效地)自动计算。
注意「有效地」这三个字。它把问题分成了三层,而这三层几乎能接住你所有的困惑:
第一层:什么能被自动计算?
有的问题根本没有算法——不是「还没想出来」,是「数学上证明了不存在」。这就是可计算性。
你平时遇到的「这个需求做不了」,绝大多数不是这一层。但偶尔会撞上:比如「写个程序判断任意程序会不会死循环」——这件事图灵 1936 年就证死了,做不了,别浪费时间。
第二层:什么能被有效地自动计算?
能算,但算不动,也是白搭。这就是复杂度。
- 排序 100 万个数,用冒泡要几分钟,用快排不到一秒——同一件事,差三个数量级
- 在两个表里找共同记录,嵌套循环要跑一整天,建个哈希表十分钟——数据结构换了,算法没换
这一层就是你最缺的那块,也是最容易补、回报最高的一块。
第三层:能算但算不动,怎么办?
不追求精确解,求「足够好」的解。近似算法、启发式、随机算法、机器学习——全在这一层。
现在很多人说「AI 会算」,其实大部分 AI 干的是这一层的事:它不保证对,它保证快,而且大多数时候够用。
四、把学科画成一摞,然后把你会的事贴上去
《计算机学科概论(第 3 版)》第 45 页有一张「系统篇」的分层图,自底向上是六层。这张图值得你亲手画一遍:
┌─────────────────────────────────────┐
│ 新技术专题 │ AI / 大数据 / 云计算 / 物联网
├─────────────────────────────────────┤
│ 网络与信息安全 │ 通信模型 / 协议 / 加密
├─────────────────────────────────────┤
│ 应用软件 │ 人机交互 / 数据库 / 软件工程
├─────────────────────────────────────┤
│ 操作系统 │ 处理机管理 / 存储 / 文件 / 设备
├─────────────────────────────────────┤
│ 程序设计基础 │ 数据结构与算法 / 程序设计语言 / 翻译程序
├─────────────────────────────────────┤
│ 计算机的运算基础 │ 数理逻辑 / 二进制 / 编码 / 逻辑电路
└─────────────────────────────────────┘
现在做一件事:把你会的每一项,往上贴。
| 你会的事 | 贴在哪一层 |
|---|---|
| 装 nginx 架站、配 HTTPS | 应用软件 ↔ 操作系统 之间 |
| 写 shell、配 cron、看 systemd 日志 | 操作系统层 |
| 配防火墙、SSH 密钥、VPN | 网络与信息安全层 |
| 装 Docker、跑容器 | 操作系统 ↔ 应用软件 之间 |
| 用 Python 调库处理数据 | 最上面那层,AI/数据 |
| 算一个脚本跑多久、为什么慢 | 程序设计基础层(空着) |
| 给一万条数据找个合适的存法 | 程序设计基础层(空着) |
| 证明这段代码对所有输入都对 | 运算基础 + 程序设计基础(空着) |
贴完你会看到一个非常明显的形状:
上面三层你跑得很快,下面两层是空的。
这就是「为什么还要补数据结构与算法」的真正答案。不是因为它重要——「重要」这句话等于没说,谁都会讲。真正的理由是:
你在做的每一件事,底下都压着这一层。你不补,它就一直在下面决定你的上限,而你看不见它。
五、学科要的四项能力,你可以自测
同一本书第 28 页把学科能力归纳成四项。我把它改成能自测的问法:
| 能力 | 自测问题 | 大多数人 |
|---|---|---|
| 计算思维 | 拿到一个模糊需求,你能不能把它写成形式化的描述? | 弱。习惯直接写代码 |
| 算法设计与分析 | 你能不能说出你的办法为什么快、快多少、最坏情况多坏? | 弱。「跑起来不卡就行」 |
| 程序设计与实现 | 能不能写出来、跑通、改得动? | 强 |
| 系统能力 | 能不能把多个部件拼成一个能用的整体? | 强。架站就在这一层 |
两头强、中间空,这是绝大多数自学者的画像。
中间这两项(计算思维 + 算法分析)不是靠多写代码就能补上的。因为写代码练的是「实现」,而分析练的是「判断」。这是两种不同的肌肉。
六、一格一格补:给路线,不给鸡汤
补的顺序不是从底往上,而是从你已经在做的事往下钻。这样每一步都有现成的例子,不会悬空。
| 你现在的状态 | 下一格补什么 | 怎么练(用你手上的活) |
|---|---|---|
| 会写脚本,不知道慢在哪 | 复杂度分析 | 拿你自己的脚本,数一数最内层那句话执行了几次 |
| 会调库,不会选 | 数据结构 | 同一份数据,用列表和用字典各写一遍,量一下差多少 |
| 会跑通,不保证对 | 正确性 | 逼自己给每个函数写「什么输入会让它错」 |
| 只会单机 | 抽象与接口 | 把你重复写的三份脚本,抽出公共部分 |
| 遇到「做不了」就放弃 | 可计算性直觉 | 分清「我不会」和「它不存在」 |
七、这组文章接下来讲什么
- 第二篇:
程序 = 数据结构 + 算法这句话,被误读了四十年。它讲的是设计顺序,不是部件构成。而且它漏了五样东西。 - 第三篇:算法分析——怎么判断一个算法好不好。大 O 到底在说什么,为什么它不告诉你「跑多久」。
- 第四篇:算法设计——五种范式,和一道题的五种写法。核心结论:更快的那个,可能是错的。
如果你只读一篇,读第四篇。如果你想把整个体系理顺,从这篇开始按顺序读。
参考
- 《计算机学科概论(第 3 版)》第 26、28、31、45 页(定义 / 四项能力 / 根本问题 / 系统分层)。文中引文均为短句摘引,其余为我的转述与改写。
- 文中对「你在哪一格」的划分、贴格子练习、补课顺序,是我自己的整理,不是原书内容。