这是一组文章的第一篇。整组讲一件事:计算机学科到底在解决什么问题,你手上那些零散的技能,各自站在哪一格。

写这组文章的起因很具体:很多人会装系统、配网络、架服务、写脚本,干得也不错,但你问他「你在计算机学科里属于哪一块」,答不上来,或者答「运维」。「运维」是岗位名,不是学科位置。

判断方法很简单:换一个岗位,你学的那些还在不在? 在,说明你拿到的是学科能力;不在,说明只拿到了操作流程。


一、先看一个错位

假设你现在能独立完成这些事:

  • 装系统、分区、配网络、改 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 页(定义 / 四项能力 / 根本问题 / 系统分层)。文中引文均为短句摘引,其余为我的转述与改写。
  • 文中对「你在哪一格」的划分、贴格子练习、补课顺序,是我自己的整理,不是原书内容。