2.13 计算、数学与工程基础
概述与动机
在每一个框架、语言和云服务之下,都潜藏着一层不会随潮流更迭的持久知识:算法在数据增长时会如何表现,网络和操作系统究竟是如何搬运字节的,一个证明或一个概率分布意味着什么,以及如何去衡量一个论断,而不只是断言它。《软件工程知识体系指南》(SWEBOK)为这层基石命名了三个知识领域:计算基础、数学基础和工程基础。本章把三者合在一起讲,因为在大型团队中它们本就是协同工作的:计算学告诉你机器是如何计算的;数学告诉你如何精确地推理正确性与不确定性;工程学告诉你如何把这种推理转化为可靠、可衡量的实践。
这一点之所以重要,原因在于:这些基本功的缺失会一直隐而不发,直到酿成灾难。一个功能在笔记本电脑上发布并运行良好,规模一上来却轰然崩溃,因为没有人推理过复杂度。一个重试循环拖垮了一个依赖服务,因为没有人把它建模为一个队列。一个”随机”令牌生成器结果被证明是可预测的,因为没有人理解它背后的数论。团队为哪种设计更快争论了一周,因为没有人做过一次测量。这些失败没有一个是因为缺了某个库,它们都是因为缺了基础。框架把机器抽象了出去,但并没有废除机器本身,而这种抽象恰恰会在大型系统所面对的负载、延迟和对抗性条件下泄漏出来。
对于企业和政府团队而言,基础知识也是让专业化分工变得安全的前提。大型组织把工作划分为前端、平台、数据、安全和 SRE(站点可靠性工程)等专业方向,并越来越依赖能按需生成看似合理代码的 AI 助手。这两种趋势带来的是同一种风险:团队里没有人能判断某种方案是否站得住脚。生成的 SQL 能扫描十亿行数据吗?那个”优化”是否悄悄改变了渐近成本?那份报告里的统计论断真的有意义吗?共享的基础知识是一种通用语言,它让专业人员能够互相评审彼此的工作,让评审者能够识破那些自信满满却是错的 AI 输出,也让组织在工具不断变化的同时保持自己的判断力。本章与软件设计(第 2.2 章)、分布式系统(第 3.3 章)、排队论(第 11.3 章)、数据架构(第 3.4 章)以及人工智能/机器学习(第 6.2 章)相互关联,这些章节都是把这些基础知识应用到具体领域的例子。
关键原则
- 抽象会泄漏: 了解你所使用的那一层之下的一层,会在抽象泄漏时救你一命。
- 渐近性决定规模: O(n) 和 O(n²) 之间的差别,就是在一千万行数据面前能跑通与彻底失败的差别。
- 正确性来自推理,而不是运气: 逻辑、不变式和证明的概念是每一个可靠系统的底层支撑。
- 不确定性是可以量化的: 概率与统计把”感觉上有点慢”变成证据。
- 先测量,再断言: 实证方法把工程与个人意见区分开来。
- 先建模,再构建: 一个小型形式化模型的成本,远低于一次大型生产事故。
- 基础知识比框架更长寿: 把投入放在二十年后依然成立的东西上。
建议
计算基础:了解抽象层之下的机器
在大型团队中,你需要熟练掌握那些决定软件能否在规模化场景下正确、高效运行的计算基础知识。
- 算法与数据结构。 选择正确的数据结构(哈希表还是树、数组还是链表、正确的索引)是大多数工程师能做出的杠杆效应最大的性能决策,而且这个决策是在任何性能剖析之前就要做出的。要熟练掌握这套标准工具库,了解每种结构让哪些操作变得低廉、哪些变得昂贵。
- 计算复杂度。 大 O 推理()描述一个算法的成本如何随着输入的增长而增长()是你日常预测系统在规模化场景下的表现(而不仅仅是笔记本电脑上的表现)的常用工具。真正重要的习惯是对每一个循环和查询都问一句:“随着数据增长,这个操作的成本是多少?“一个嵌套遍历用户记录的循环,在测试中风平浪静,在生产环境中却是致命的。
- 操作系统与并发。 进程、线程、内存、调度、文件系统,以及并发中的各种陷阱(竞态条件、死锁、资源争用)解释了绝大多数棘手的生产环境缺陷。理解操作系统实际在做什么,能揭开延迟毛刺和资源耗尽背后的神秘面纱。
- 网络。 延迟、带宽、丢包,TCP 与 UDP(可靠传输协议与轻量传输协议)之分,DNS(把名称解析为地址的域名系统),TLS(对连接进行加密的传输层安全协议),以及分布式通信的种种现实,构成了每一次服务调用的底层支撑。经典的分布式计算谬论(网络并不可靠、延迟并非为零、带宽并非无限)是第 3.3 章会反复出现的网络课程。
- 数据库。 查询规划、索引、事务、隔离级别和范式化决定了数据访问是否快速且正确。第 3.4 章专门讨论数据架构;这里的基础是理解为什么一个缺失的索引会把一个毫秒级查询变成一次全表扫描。
- 计算机体系结构。 缓存、内存层次结构、CPU 流水线和 I/O 成本,能解释仅靠性能剖析无法说明的性能意外。对缓存友好的访问模式,其性能表现有时能比”聪明”的算法高出一个数量级。
- AI/ML 基础与人因工程。 对人工智能与机器学习(AI/ML)()即模型、训练与推理()有足够的理解,才能负责任地使用它们(第 6.2 章),再加上对人因工程(可用性、认知负荷、易出错的界面)有足够的基础,才能构建出人们真正能够安全操作的软件。
数学基础:精确地推理正确性与不确定性
数学是精确推理的语言。你不必成为数学家,但以下这些概念在日常工程中是必不可少的。
- 逻辑与证明。 命题逻辑和谓词逻辑是每一个条件语句、每一个不变式、每一条测试断言的底层支撑。陈述前置条件、后置条件和不变式()也就是推理什么必须为真()正是你写出正确的并发代码、并在事故发生之前捕获边界情况的方法。
- 集合论与关系。 集合、关系和函数是关系模型、类型系统的数学骨架,也是清晰思考成员归属、唯一性和映射关系的基础。
- 图。 依赖图、网络拓扑、构建顺序、路由,以及社交/组织结构,本质上都是图;掌握遍历、最短路径和环检测的思路具有广泛的适用性。
- 有限状态机。 协议、工作流、UI 状态和生命周期管理都可以被清晰地建模为状态机,这能让非法状态无法被表示,也能让边界情况被穷举出来。
- 概率与统计。 性能百分位数、容量规划、A/B 测试(在真实流量上比较两个版本,看哪个表现更好)、可靠性估计,以及机器学习,全都建立在概率与统计之上。知道均值和 p99(第 99 百分位,即接近最坏情况的值)之间的区别,理解方差,并能够判断一个结果是否显著,正是区分真实结论和噪声的关键,这也是排队论(第 11.3 章)背后的数学基础。
- 与密码学相关的数论。 模运算、素数和离散对数,是保护一切安全的公钥密码学的基础。你不应该自己实现密码学算法,但理解为什么密钥长度、随机性和算法选择很重要,正是让你避免那些破坏安全性的低级错误的关键。
工程基础:把推理转化为可靠的实践
工程基础是让软件工程成为一门真正的工程学科、而不仅仅是一门手艺的关键。
- 实证方法。 提出假设、设计实验、进行测量,让证据而不是资历或直觉来裁定问题。无论你是在比较两种设计、诊断一次回归,还是评估供应商的宣称,测量都胜过争论。
- 测量。 明确定义你在测量什么、如何测量,包括单位和误差范围。糟糕的测量(误导性的平均值、不具代表性的基准测试、精心挑选的运行结果)比没有测量还要糟糕,因为它把个人意见洗白成了数据。
- 对结果进行统计分析。 把上面提到的概率与统计应用到真实的测量结果上:报告分布和百分位数,考虑方差,避免仅凭一次运行或过小的样本就下结论。
- 抽象与建模。 工程的核心动作是构建一个简化模型,它抓住重要的东西、隐藏不重要的东西,同样重要的是,它清楚自己的局限所在。一个粗略估算的容量模型,或一张小小的状态机图,能在代码写出来之前就暴露设计缺陷。
- 标准。 工程的进步靠的是站在共同认可的标准(协议、格式、接口和实践规范)之上,而不是重复造轮子。在大型团队和政府团队中,标准也是独立构建的各部分能够互相协作、工作能够被审计的方式。
- 根因分析。 出了故障时,有纪律的根因分析(RCA,如”五个为什么”、故障树、无责事后总结)找到的是根本原因,而不是最表面的症状,这样修复才能真正生效。可以把它看作是把实证方法应用于故障排查。
权衡:优点与缺点
| 决策 | 优点 | 缺点 |
|---|---|---|
| 广泛投资于基础知识 | 判断力持久;专业化分工和 AI 使用更安全;扩容意外更少 | 上手更慢;占用的时间会被”赶紧发布”的压力所排斥 |
| 依赖框架/抽象 | 交付速度快;前期需要了解的东西更少 | 一旦抽象泄漏就会失效;没有人能诊断深层问题 |
| 构建前先做形式化建模 | 以低成本捕获设计缺陷;形成共同理解 | 前期需要投入精力;模型可能过度简化现实 |
| 凭实证测量 | 基于证据决策;终结争论 | 需要严谨性;糟糕的测量会误导 |
| 依赖 AI 生成代码 | 速度快;样板代码有人代劳 | 看似合理实则错误的输出,需要基础知识才能识破 |
反复出现的权衡是眼前的速度与日后的判断力之间的取舍。基础知识很少能帮你更快地交付这一个功能。它们真正的作用,是帮助团队在成千上万个功能上做出正确的决策,避免那些被抽象所掩盖、代价高昂又难以诊断的故障。陷阱在于:忽视基础知识的代价是延后而分散的,而学习基础知识的代价却是即时而显而易见的。所以在交付压力之下,基础知识的投入总是长期不足,直到一次扩容事故或安全事故逼你还债。
与团队讨论的问题
团队里谁在评审安全敏感代码,他们是否理解为什么密钥长度和随机性真的很重要? 你永远不应该自己实现密码学算法,但你仍然要选择库、确定密钥长度、生成随机数来源,而其中任何一处的自信错误决策(一个可预测的令牌生成器、一个供应商兜售的自研方案)都会悄悄破坏安全性,直到被攻击者发现为止。公钥密码学背后的数论(模运算、素数、离散对数)正是让评审者能够拒绝一个天真的选择,而不是点头放行的关键。带一份真实的产物到会议上:指着生成令牌或会话密钥的代码,问问谁有资格说这段代码是可靠的。如果诚实的答案是没有人,那这个缺口就不是缺一个库,而是需要培养或招聘具备这项特定基础能力的人,并把与安全原语相关的决策交给有这种能力的人。
我们招聘和晋升的标准是基础推理能力,还是框架熟练度,而把差距留到以后再付代价? 忽视基础知识的代价是延后而分散的,而学习基础知识的代价却是即时而显而易见的,所以在交付压力之下,这类知识总是长期投入不足,直到一次扩容或安全事故逼你还债。在一个把工作划分为前端、平台、数据和 SRE 等专业方向、并越来越依赖能生成看似合理代码的 AI 的大型团队中,共享的基础知识是让专业人员能够互相评审彼此工作、能够识破那些自信满满却是错的输出的通用语言。带上你们的面试评分标准和晋升标准:它们考察的是候选人能否推理复杂度、测量和正确性,还是只考察他们是否了解今年流行的框架?这个答案应该重塑你们招聘、指导和保护学习时间的方式,因为在 AI 辅助的时代,判断方案是否可靠这种人类能力,正在成为稀缺而高价值的技能。
当两位工程师就某个设计的性能产生分歧时,我们是去测量,还是听资历更深的人的? 实证方法正是让这变成工程、而不是个人意见的关键:提出假设、做实验,让证据来裁定问题,无论你是在比较两种设计、诊断一次回归,还是核实供应商的宣称。大型团队的陷阱在于,争论往往由自信和资历胜出,一场测量一小时就能结束的争论,却在辩论中消耗掉一整周。带上一次最近的设计分歧,问问它实际上是如何解决的:靠数据,还是靠房间里嗓门最大的人?行动是让测量成为设计评审的常规环节,明确单位、误差范围和分布,而不是精心挑选的单次运行结果,这样”感觉更快”就会被整个团队都能信任的 p95 或 p99 数字所取代。
我们的设计和代码评审是否真的会问”随着数据增长,这个操作的成本是多少?“,还是只有到了规模化场景下才发现答案? 渐近推理是这份清单里杠杆效应最大的日常技能,因为一个 O(n²) 的循环在测试数据下毫无察觉,在生产环境中却是致命的,而捕获它成本最低的地方是评审环节,而不是事故现场。大型团队中与之竞争的压力是吞吐量:在截止日期压力下的评审者只会检查眼前样例的风格和正确性,很少去问代码在一千万行数据下会如何表现。带上一个最近的合并请求,把这个问题应用到每一个循环、查询和连接操作上,大声读一遍,然后问问你们的评审清单或模板是否真的提示过这个问题。在数据量会持续多年增长的企业或政府系统中,一次缓慢的查询可能会违反服务级别协议、或延误公民的福利申请,因此要把复杂度这个问题变成评审中一道必须书面确认的关卡,这样这个习惯就不会仅仅取决于当天碰巧是谁在评审。
我们如何判断 AI 生成的代码是否正确、可扩展、安全,实际上又是谁有资格做出这个判断? 生成代码速度快,也很容易被不加批判地接受,而它自信满满地犯错的频率也足够高,以至于在没有基础知识的情况下合并它,正是细微的扩容和安全缺陷进入代码库的方式。大型团队面对的张力是真实存在的:这个工具存在的意义就是加快人的速度,如果要求对每一条建议都进行深度评审,就会抹掉这份收益,所以你必须决定哪些类别的生成代码(一个安全原语、一个热路径查询、一次并发相关的改动)始终需要专家审查,哪些可以走更轻量的检查。带上一批最近合并的 AI 辅助改动,逐一问:团队里谁能自信地说它是可靠的,以及是否真的有人这样做了。对于要向审计人员负责的企业或政府组织,要为高风险类别指定负责的评审人,并记录下是一位具备相关基础能力的人签字确认,因为当一个生成的缺陷流入生产环境时,“这是模型写的”不是一个站得住脚的答案。
我们的哪些高风险设计值得在写代码之前先做一个小型形式化模型,这里有没有人知道该怎么构建这样一个模型? 一次粗略的容量估算、一个让非法状态无法表示的有限状态机,或者一份集合论式的数据规范,其成本远低于它所预防的那次生产事故,然而建模恰恰是团队在交付压力下最先跳过的基础工作。与之相对的考量是,模型需要前期投入精力,却没有已发布的功能可以展示,而一个过度精细的模型也可能因为掩盖了自身的局限而产生误导,所以真正的技能在于选择能暴露真实风险的最小模型。带上两三个爆炸半径最大的设计(一个支付流程、一个资格判定引擎、一个并发密集型流水线),问问一页纸的模型是否本可以暴露出你后来才在生产环境中撞上的边界情况。在缺陷可能带来法律或公共后果的企业或政府场景中,一个小型形式化模型还能为监督机构提供一份可供评审的产物,以及一个可以站得住脚的信任理由,所以要把建模能力当作一项需要刻意培养的能力,而不是一种奢侈品。
行业视角
初创企业。 团队规模小、跑道有限,你承受不起一次需要数天才能诊断出来的深层故障,所以要保留那些能立即见效的少数基础习惯:问问每个查询随着数据增长的成本是多少,并在相信一个性能宣称之前先测量一个真实的百分位数。不要去构建你用不上的形式化方法的严谨性,但要确保至少有一位创始人能够推理复杂度和随机性,因为一个可预测的令牌生成器,或一次意外的全表扫描,都可能在你找到产品市场契合度之前就把你拖垮。对于任何安全敏感的部分,依赖经过充分分析的标准库,而不是自己发明。
小型企业。 没有专职的专家,预算又紧张,把基础知识当作一个”购买还是自建”的过滤器:优先选择托管数据库、托管身份认证服务和标准密码学,让那些困难的部分交给理解你没有时间去学的数论的人去处理。在你确实要写代码的地方,最廉价的保障是安排一位评审者,让他问那个扩容问题,并检查报告的数字是百分位数,而不是好看的平均值。把你稀缺的基础知识精力,用在那几个错误决策一旦做出就很难逆转的地方(索引、密钥管理、容量)。
企业。 在规模化、跨越众多团队的场景下,基础知识是让专业化分工和 AI 辅助保持安全的共同语言,所以要把期望标准化:把复杂度推理、带有恰当统计方法的测量,以及根因分析,变成设计评审和代码评审中书面的关卡。治理和审计能直接从中受益,因为一份有文档记录的复杂度检查、一份记录在案的基于百分位数的基准测试,以及一份无责事后总结,正是评审者和监管者所要求的那种证据。投资于指导和内部教育,让这些知识留存于组织之中,而不是留存于少数不可替代的个人身上。
政府。 采购规则、透明度和公共问责,让基础知识既是一项工程资产,也是一项合规资产。坚持使用标准化的、经过充分分析的密码学,拒绝任何供应商自研的方案;把资格判定和工作流逻辑建模为有限状态机,以便监督机构能够审查这些规则;在向公众证明一套系统的合理性时,报告 p95 和 p99 延迟,而不是平均值。由于合同和审计要求一份站得住脚的、以证据为基础的记录,要把测量、建模和根因分析当作交付物,让系统对公民和评审者而言都是可解释的。
示例
初创企业。 一家两人创始的分析类初创公司发布了一个仪表盘,在他们为数不多的几个试点账户身上感觉快如闪电,可第一个真正的客户加载一年的数据时,系统却陷入停滞。一位创始人推理了复杂度问题,发现一个没有索引的查询在每次页面加载时都在做全表扫描,把一次毫秒级的查询变成了以秒计的等待。加上正确的索引解决了问题,一次对 p95 延迟(而不是那个掩盖了缓慢尾部的平均值)的快速测量,用证据而不是直觉确认了这次改进的效果。缺失的基础不是某个工具,而是”随着数据增长,这个查询的成本是多少”这个提问的习惯,他们把这个问题加进了自己的合并前检查清单。
企业。 一家零售商的结账服务通过了每一次测试和演示,却在一个促销日崩溃了。根因分析发现了一个 O(n²) 的循环,它把每一个购物车商品与每一条目录促销规则逐一比对:用三件商品的测试购物车毫无察觉,在真实购物车和峰值负载下庞大的促销规则集面前却是致命的。一位推理过复杂度的资深工程师把它替换为一次哈希表查找(O(n)),一个小型排队模型(第 11.3 章)则设定了安全的并发上限。这次修复只是一次数据结构的选择;缺失的基础是”随着数据增长,这个操作的成本是多少”这个提问习惯。该组织把复杂度推理加进了设计评审清单,让这个问题在事故发生之前、而不是之后被提出。
政府。 一家正在现代化一套遗留系统的福利机构,有意识地运用了工程和数学基础。分析师把资格判定工作流建模为一个有限状态机,这使得非法的状态转换无法被表示,并暴露出旧系统多年来一直处理不一致的边界情况。他们使用集合论式的关系来规定数据,以保证唯一性和引用完整性,并选择了标准化的、经过充分分析的密码学,对数论理解得足够深入,从而能够正确确定密钥长度,并拒绝了一家供应商自研的方案。当性能问题出现时,他们使用恰当的统计方法进行测量,报告 p95/p99 延迟,而不是平均值,这给了监督机构一个站得住脚的、基于证据的理由来接受这套系统。
商业理由:动机、投资回报率与总拥有成本
基础知识的回报,来自于预防了代价最高昂的一类故障:那些只在规模化场景下、负载之下,或在攻击之下才会出现的故障()正是系统已经在生产环境运行、修复成本最高的时候。一次因为有人理解随机性和密钥长度而从未发生的安全事故,一次因为一开始就选对了数据结构而根本不需要的扩容重设计:其中任何一件,都足以偿还多年的基础知识投资。这项回报不是一个财务科目,而是一种”反复出现、难以诊断的灾难不再发生”的状态,以及一支能够持续做出正确决策的团队。
在总拥有成本方面,基础知识的维持成本异常低廉,因为它是知识,而不是工具或许可证,而且它贬值得很慢。大 O、概率和实证方法在今天和几十年前一样成立,而框架却每隔几年就要更新换代。要投资的地方是招聘、指导,以及保护学习时间:让初级工程师与那些会大声说出自己复杂度推理过程的资深工程师结对,运行能教会人根因分析的无责事后总结,让测量和建模成为设计评审的常规环节。在 AI 辅助的时代,这项投资回报率可以说还在上升。生成代码速度快,也很容易被不加批判地接受,所以判断方案是否可靠(这段代码正确吗?能扩展吗?安全吗?)的人类能力,正在成为稀缺而高价值的技能。提高质量最廉价的方式,往往就是提高评审工作的人的基础知识熟练度。
反模式与陷阱
- 只懂框架: 熟练使用某个工具,却不理解其底层的机器,导致没有人能诊断深层故障。
- 忽视渐近性: 发布在测试数据上能跑通、却在生产数据上崩溃的代码,因为从未考虑过复杂度。
- 把平均值当作真相: 报告平均延迟或单次基准测试结果,却错过了真正伤害用户的长尾。
- 自研密码学: 在不理解其数论原理的情况下发明安全原语,结果这些原语是有缺陷的。
- 头痛医头: 只修补眼前的错误,不做根因分析,导致故障以新的形式再次出现。
- 形式主义式优化: 不经测量就”优化”,往往让事情变得更慢,或在不知不觉中改变了渐近成本。
- 不加批判地接受 AI: 在没有基础知识来判断代码是否正确、可扩展、安全的情况下,合并看似合理的生成代码。
- 把基础知识当作”学院派”: 把基本功斥为与”实际”工作无关,然后在生产环境中为这种缺失付出代价。
成熟度模型
- 第 1 级,启动: 知识仅停留在框架层面;扩容和安全故障总是让团队措手不及;决策依赖直觉和资历;AI 输出被不加批判地接受,基础知识的缺口只有在事故发生后才被注意到。
- 第 2 级,发展: 部分资深工程师能够推理复杂度、测量和正确性,一些好习惯在局部出现,但这些知识局限于个别人,在各团队之间应用不一致,评审中也不作要求。
- 第 3 级,标准化: 基础推理能力已被记录在案,并被期望在整个组织范围内普及:复杂度和数据结构检查、带有恰当统计方法的测量,以及根因分析,会在设计和代码评审中常规出现,有书面检查清单作支撑,也是每个团队招聘和成长要求的一部分。
- 第 4 级,管理: 组织会依据基线来衡量自身的基础知识健康度。它追踪评审中是否覆盖了复杂度问题、可追溯到某个基础缺失(未加索引的查询、弱随机性、无边界的循环)的事故占比、与上一版本相比基于百分位数的基准测试,以及 AI 辅助代码的缺陷逃逸率,然后依据这些证据、而不是意见,来决定”通过”或”不通过”。
- 第 5 级,编排: 基础知识在整个组织范围内持续改进、持续整合。指导、内部教育和建模已是常态;测量和根因数据被反馈进标准和培训之中;基础知识被有意识地用于评估 AI 生成的工作;当框架和抽象失效时,团队能够适应,从第一性原理出发进行推理。
讨论话题
- 你们团队上一次抽象泄漏是什么时候,有没有人具备快速诊断它的基础知识?
- 你们的设计或代码评审是否真的会问”随着数据增长,这个操作的成本是多少?”
- 你们如何评估 AI 生成的代码是否正确、可扩展、安全,团队里谁能做到?
- 在哪些地方,你们报告的是平均值,而百分位数和方差本可以说出真实的故事?
- 团队整体上哪项基础最薄弱(复杂度、概率/统计、网络,还是实证方法),这会让你们付出什么代价?
- 随着专业化分工不断深化、工具不断变化,你们如何维持基础知识?
关键要点
- 基础知识是框架之下那层持久不变的东西:计算学(机器如何计算)、数学(如何精确推理),以及工程学(如何测量与建模)。
- 抽象会泄漏,而基础知识正是让团队能够在泄漏发生时(通常是在规模化、负载或攻击之下)诊断故障的关键。
- 渐近推理是杠杆效应最大的日常技能:问问每一个循环和查询随着数据增长的成本是多少。
- 概率、统计和实证方法把个人意见变成证据:要测量并报告分布,而不只是平均值。
- 先建模、先推理,再构建: 有限状态机、不变式和小型容量模型能以低成本捕获缺陷。
- 基础知识通过赋予团队评估方案是否可靠的共同判断力,让专业化分工和 AI 辅助变得安全;它们维持成本低廉,贬值缓慢。
参考资料与延伸阅读
- IEEE Computer Society, SWEBOK Guide(第 4 版):计算基础、数学基础和工程基础知识领域。
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein, Introduction to Algorithms(CLRS):算法、数据结构与复杂度。
- Martin Kleppmann, Designing Data-Intensive Applications:数据结构、数据库、分布式系统及其在规模化场景下的权衡。
- Andrew S. Tanenbaum, Modern Operating Systems and Computer Networks:操作系统与网络基础。
- Kenneth H. Rosen, Discrete Mathematics and Its Applications:面向计算的逻辑、集合、图与数论。
- Bruce Schneier, Applied Cryptography / Ferguson, Schneier, Kohno, Cryptography Engineering:密码学的数论基础与实践。
- Andy Oram and Greg Wilson (eds.), Making Software: What Really Works, and Why We Believe It:软件工程中的实证方法。
- Peter Deutsch and James Gosling, “The Eight Fallacies of Distributed Computing”:第 3.3 章会反复出现的网络假设。
- Wikipedia: “Big O notation,” “Finite-state machine,” “Five whys,” “Public-key cryptography.”