从一个问题到一个软件系统(全系列总装)
复习
- 需求与边界、分解与接口:把问题变成设计
- 测试、构建、维护:让软件能被信赖地交付与长期使用
- 编译原理:把源码变成可运行的机器码
TL;DR
- 从“一个问题”到“一个软件系统”,是一条完整的闭环
- 需求、程序、编译器、操作系统、网络、算法、硬件层层接力
- 每一层都建立在下面几层之上
- 整个系列的主线:分层、抽象与取舍
正文
这是整部指南的最后一章。让我们把从第一枚比特开始、一路走来的所有内容,串成一条完整的线:从一个真实的问题出发,直到它在机器上运行起来,并长期被使用。
从问题开始
一切都从一个问题开始:有人想解决某件事。于是:
- 理解问题:弄清需求,划清边界——不做这一步,后面全是白费
- 设计:把它分解成模块,定好接口,约定契约
- 写程序:用高级语言把设计写成代码
到这里,你手里有一份源码。但它还只是文字。
让它成为可运行的程序
接着,编译器接过源码(还记得它的一生吗):
- 前端读懂它:词法、语法、语义
- 中端优化它:常量折叠、死循环删除、循环优化……
- 后端落成机器码:指令选择、寄存器分配、栈帧
- 再经过汇编、链接,成为可执行文件
这份可执行文件,最终由操作系统装载进内存、分配资源、开始运行。而它在内存里的样子、它的地址空间、它用的设备与文件——正是操作系统那一部分的内容。
让它连上世界
如果程序需要和远方的机器通信,就轮到网络:
- 数据从应用出发,经传输层、网络层、链路层一路封装
- 跨过交换机、路由器,一跳一跳接力
- 在另一台机器上被层层拆开,交给对应的程序
从一根线传一个比特,到一次完整的网页访问,网络把“远方”接了进来。
让它跑得聪明
而无论哪一层,算法与数据结构都在背后提供支撑:
- 操作系统调度进程、缓存数据、管理内存
- 网络计算路由、缓存内容、解析域名
- 编译器做词法语法分析、优化、寄存器分配
每一个“怎样更快、怎样更好”的问题,最终都会落到“怎样组织数据、怎样安排步骤”上——这正是算法与数据结构那一部分的主题。
让它能长期活着
最后,一个程序要成为真正的软件系统,还要:
- 被测试,保证它是可信的
- 被构建,变成可交付的产物
- 被维护,在变化中长久演化
- 在安全与可靠上有基本的保障
这些,就是软件构造那一部分补上的最后一段路。
回到最初
把这一切串起来看:
问题 → 需求 → 设计 → 代码
→ 编译器(词法·语法·语义·优化·后端)
→ 操作系统(装载·内存·进程·文件·设备)
→ 网络(封装·转发·端到端·应用)
→ 软件(测试·构建·部署·维护)
→ 运行在硬件上(逻辑门·寄存器·时钟)
你看,每一层都站在下面几层之上:软件依赖操作系统,操作系统依赖硬件,网络把一台台机器连成世界,而算法让每一层都更高效。整部教程反复讲的那几句话,此刻应该都能体会了:
- 懒是人类进步的第一动力
- 在计算机科学里,没有什么问题是加一层解决不了的
- 人类所有知识都来源于好奇心和解决问题
- 所有庞大学科知识体量均由积累而成,不会一蹴而就
计算机科学看起来庞大,但拆开看,不过是一层层简单的约定,一次次务实的取舍,一代代人积累的结果。
而这门学科的未来,以及下一个问题的答案,不在任何一本书里——它在下一个愿意好奇、愿意动手解决问题的人身上。
也许,就是你。
思考题 1
从“一个问题”到“一个软件系统”,大致经历了哪些环节?
思考题 2
回顾整个系列,你觉得贯穿始终的主线是什么?
小结
知识点
- 从问题到软件系统是一条完整闭环
- 需求、设计、代码、编译、运行、网络、维护层层接力
- 每一层都建立在下层之上
- 全程主线是分层、抽象与取舍
参考资料
- Wikipedia(zh):计算机科学:研究计算与信息处理的学科
- Wikipedia(zh):系统开发生命周期:从需求到维护的完整过程
思考题答案(仅供参考)
思考题 1
大致经历:理解需求与边界、设计模块与接口、编写代码、编译(词法·语法·语义·优化·后端)与链接、由操作系统装载运行、必要时通过网络通信、以及测试、构建、部署、维护等软件工程环节,最终运行在硬件之上。
思考题 2
参考答案:分层、抽象与取舍。 用一层层抽象把复杂性封装起来(硬件→操作系统→网络→应用),每遇到难题就“加一层”;而每一层、每个设计又都在性能、空间、复杂度之间做取舍。整部教程,就是这条主线的不断重演。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪