Edsger W. Dijkstra -- 从“有害”到“结构化”:一位先驱的编程哲学革命

张开发
2026/4/12 2:50:25 15 分钟阅读

分享文章

Edsger W. Dijkstra -- 从“有害”到“结构化”:一位先驱的编程哲学革命
1. 混乱时代的编程困境GOTO为何成为众矢之的1968年的计算机世界正处在野蛮生长的阶段。那时的程序员们面对满屏跳转的GOTO语句就像在迷宫里摸黑前行。我记得第一次看到这种代码时的震撼——上千行的BASIC程序里布满了GOTO 120、GOTO 450这样的指令要理解程序逻辑就得像侦探一样在各个行号间来回翻找。Dijkstra在《Go To Statement Considered Harmful》中犀利地指出程序员的思维会不自觉地沿着GOTO的指向思考。这就像用橡皮筋把不同的乐高积木强行绑在一起表面看是个整体实则一碰就散。当时有个经典案例某银行系统因为GOTO滥用导致循环无法退出最后不得不每天凌晨重启服务器。最要命的是调试这种代码。有次我帮朋友修改一个用FORTRAN写的科学计算程序其中有个GOTO跳转错了行号导致计算结果偏差了30%。我们花了整整三天用纸笔画出所有跳转路径才找到这个幽灵bug。这种经历让我深刻理解了Dijkstra的愤怒——他称这种编程方式是智力上的虐待。2. 一封改变历史的公开信Dijkstra的编程宣言1968年3月那封著名的信件引爆了编程界的圣战。Dijkstra原本拟的标题是《反对GO TO语句》但编辑担心太激进改成了相对温和的《Go To Statement Considered Harmful》。这个标题后来成了技术圈的经典句式模板就像我们现在常说的XXX被认为是有害的。信中提出的核心观点现在看来理所当然但在当时堪称革命程序质量应该用智力可管理性来衡量GOTO破坏了程序的局部推理能力程序员应该能静态地理解代码行为反对声浪来得又快又猛。IBM的某位资深工程师公开嘲讽不用GOTO难道要用绳子把数据捆起来吗更有趣的是当时很多反对者后来都成了结构化编程的拥护者。就像我认识的一位老程序员说的起初觉得Dijkstra在剥夺我们的自由后来才发现他给了我们真正的自由——不被bug追着跑的自由。3. 结构化编程的星星之火从争议到共识《Notes on Structured Programming》这份报告最初只复印了20份却在程序员间像野火一样传播。我收藏的第五版复印稿上还能看到前几位读者的批注有人写道这就像给代码装上了红绿灯报告中最具颠覆性的是提出了程序设计的三种基本结构顺序结构直线前进的执行流begin statement1; statement2; ... end选择结构明确的决策分支if condition then statement1 else statement2循环结构可控的重复执行while condition do statement这些现在教科书里的基础内容在当时就像黑暗中的灯塔。有个生动的比喻结构化编程前的代码像意大利面条之后则像精心堆叠的三明治——你可以一层层拆解而不弄乱其他部分。4. 范式革命的深远影响从理论到实践Dijkstra的思想催生了现代软件工程。1970年代诞生的Pascal语言是第一个全面拥抱结构化编程的主流语言其设计者Niklaus Wirth说我们只是把Dijkstra的哲学变成了编译器能理解的语法。我在大学时用Turbo Pascal写第一个图形程序时就感受到了这种范式的力量——即使代码写到上千行仍然能保持清晰的逻辑脉络。更深远的影响体现在这些方面代码可读性新人能更快理解项目团队协作不同程序员写的代码风格趋同错误预防减少了90%的控制流错误维护成本修改代码时不用担心牵一发而动全身现代IDE的代码折叠、流程图生成等功能本质上都是结构化编程思想的延伸。就像我常对团队说的好代码应该像好散文——即使去掉所有注释也能让人读懂作者的思路。5. 超越时代的哲学思考程序作为数学实体Dijkstra最超前的观点是程序应该像数学证明一样严谨。他在埃因霍芬理工大学任教时要求学生用数学符号先写出程序规范再推导出实现代码。这种方法看似低效却培养出了整整一代重视正确性的工程师。有个经典教学案例如何验证二分查找的正确性。Dijkstra会要求先定义有序数组的数学表达∀i: 0 ≤ i N-1 ⇒ a[i] ≤ a[i1]然后推导循环不变式left ≤ right ∧ (∀i: 0 ≤ i left ⇒ a[i] target) ∧ (∀i: right i N ⇒ a[i] target)这种思维训练让我受益匪浅。十年前我参与开发航空软件时团队采用类似方法最终交付的代码实现了零运行时错误。正如Dijkstra预言的那样计算机科学本质上是数学的一个分支。6. 争议与反思结构化编程的局限与演进当然任何技术主张都有其历史局限性。Dijkstra晚年也承认过度严格的结构化可能影响表达力。现代语言中的break、continue等控制语句可以看作是在保持可读性前提下的合理妥协。函数式编程的兴起带来了新的视角。当我在JavaScript项目中使用map/filter时发现它们本质上是用高阶函数实现了更安全的结构化控制流。React等框架的声明式UI则是将Dijkstra的思想延伸到了交互领域。有趣的是GOTO在底层系统编程中从未完全消失。Linux内核中仍有少量谨慎使用的goto主要处理错误清理。这提醒我们编程范式的进化不是非此即彼的替代而是不断寻找最合适的抽象层级。

更多文章