上世纪五六十年代,高级语言还没普及,很多人用汇编写程序,汇编代码运行效率高,但是有个致命的缺点:不容易看懂,维护困难。
程序设计是少数聪明人干的事情,他们智力超群, 写代码也不讲什么规则,可以随意使用灵活而又强大的 Goto,写出只有自己能懂的代码。
但是到了六十年代中后期,事情就慢慢不对了,计算机的计算能力提升速度远远超过程序员,软件规模和数量随之急剧上升, 出现了一堆问题:项目预算超支,项目难以管理,代码质量很低,软件不符合需求,这该怎么办?
北约会议
1968年,“北约软件工程大会”在风景如画的德国小镇Garmisch召开(我很奇怪为什么这个会议以北约的名义牵头,有知情的同学请告知。)
会议指出:软件的复杂度已经变得人脑无法掌控,我们已经处于严重的软件危机当中!
会议强调:软件的生产有必要建立在某些理论基础和实践指导之上!
会议要求:各单位要切实加强对其他学科的学习,实施软件软件工程的办法,努力提高程序设计的效率和质量。
可是理论基础和实践指导在哪里呢?
1968年的 Dijkstra
每当危机到来,总会有大神出手相救,这一次是 Dijkstra。
学编程的同学肯定知道他,《数据结构和算法》中有他的Dijkstra算法,《操作系统》中有他的信号量,银行家算法,他还在程序设计,分布式计算,并行计算,编译器等很多领域做出了开创性贡献,于1972年获得计算机界最高奖:图灵奖。
Dijkstra大神经过研究,于1968年在ACM上发表了一篇论文,名字叫做《Go to 语句有害论》,要求废除 Go to 语句!
这篇战斗檄文一下子就使编程界炸了锅,支持 Goto 语句的人觉得他们的权益受到了极大的侵犯:没有 Go to 语句,程序流程怎么跳来跳去,以后怎么写代码?
Dijkstra 准备充分,他本人在50年代就用机器代码编写了大量程序,清楚地知道 Go to 语句的危害, 但是为了以理服人, 他搬出了一个著名的、被证明的理论:
无论是什么程序,不管多么复杂,都可以用三种基本的结构来表达:顺序,分支,循环。
所以,你们不用再瞎BB了, 不用 go to 语句也能写程序。
结构化编程
更进一步,Dijkstra 创造了一个词:结构化编程,它包括这些元素:
控制结构:顺序, 分支,循环,还有著名的递归
子程序:也叫过程,方法,函数,可以封装一系列语句让别人调用。
代码块:如if...fi,Begin...END , {....}
这几乎就是现代编程语言最基本的元素了,软件工程这座大厦的地基终于打好, 结构化编程掀起了一场革命:
自顶向下分析问题
模块化设计
高内聚、低耦合
瀑布式开发方法
......
结构化编程大大降低了编程的复杂性, 必须感谢这些大神,让我等资质平庸的人也能投身于软件编程的伟大事业当中,如果把我扔到五六十年代的 Go to 洪流中,我可能活不过三集。
对 Go to 的争论一直没有停歇,包括高纳德这样的大神也卷入进来,发表文章《Structured Programming with go to Statements》,他分析了许多常见编程任务,然后发现其中的一些使用 Go to 将得到最理想的结构。例如:跳出嵌套循环,多个分支的跳出等,所以现在很多编程语言依然保留着 goto 这个关键字。
致命问题
随后几年,结构化编程运动如火如荼,人们写的程序越来越复杂,结构化编程的两个致命问题逐渐暴露:
1. 维护全局变量变成噩梦
子程序(函数)虽然封装了相同的代码逻辑,成为黑盒子,但是多个子程序(函数)需要共享信息的时候,就需要全局变量,全局变量一旦变多,维护就变成噩梦。
2. 子程序(函数)的复用性太差
函数是一个有输入、输出的简单的逻辑单元,其他程序可以通过调用公用函数来实现复用,但是这种复用的层次太低。
比如:我们想定义一个这样的主程序:
里边包含一些逻辑,但是有些步骤是虚线,表示希望在运行时能动态的替换成用户自己的东西(没错,这其实就是一个框架了!) ,结构化编程就有点儿着急了。
也就是说,我们无法复用这个主程序的结构。
C语言可能会跳出来:用函数指针来做啊。没错,函数指针能实现,但是属于高级技巧,不是普罗大众程序员能玩的, 何况有些语言还不支持。
1967年的 Simula
时间倒退一年到1967年,挪威的两名科学家 Ole-Johan Dahl 和 Kristen Nygaard 发明了一个叫做 Simula 67 的语言,这个语言和当时流行的 Fortran, COBOL, Basic 全然不同, 它不但支持类,还支持继承,多态这些新鲜的概念。
不过由于当时的计算机硬件性能低下,而这些概念又过先进,所以在很长时间内都没人注意到。
随着结构化编程缺陷的暴露,人们发现 Simula 67 这门语言的特征正好可以解决上面的两个问题:
1. 类可以把函数和成员变量组织在一起,消除全局变量
使用权限控制,可以使得实例变量对外不可见。
2. 通过多态,可以实现对主程序的复用
主程序只调用接口或者缺省类,使用者提供实现类,两者结合起来,完成业务功能。
大神程序员可以集中精力搞定那些最基础,最重要的东西,创建出通用的框架和类库让程序员使用。我等普通人只需要专注业务逻辑即可, 又可以快乐地搬砖了!
使用面向对象的技术,代码的复用层级从简单的函数进化到类和框架,不仅如此,还有些程序员从框架和类库中抽取出了可以重用的思想:模式。
面向对象技术从60年代的 Simula 67 起源,70年代出现了 Smalltalk,80 年代出现了 C++, 到了90年代,Java 横空出世,面向对象编程终于成为主流。
2001年,图灵奖姗姗来迟,颁给了发明 Simula 67 的 Ole-Johan Dahl 和 Kristen Nygaard。
尾声
1967年和1968年真是神奇的两年, 面向对象技术发明, 结构化编程运动开启。
表面看,这两项技术没什么大不了的,但是它们都降低了软件开发的复杂度,使得普通人也能参与到搬砖的伟大事业当中,这才造就了繁荣的软件编程行业和互联网。
请大家切记,使用某种更高级的技术,不能代表你就能开发出高级的程序,关键在于人。 用面向对象的语言,写着面向过程的程序,这样的人大有人在。
所以,如果有人再宣称
OOP大法好
设计模式大法好
函数式编程大法好
XXX框架大法好
XXX大法好
你不用多费口舌,只需要问他一个直击灵魂的问题:你用这个技术,是不是降低了你所在领域的复杂度呢?是不是提高了可维护性和重用性?看看他怎么回答吧!
后记:本文是受到《面向对象是怎样工作的》一书的启发所写,这本书比较深入地讲述了面向对象的技术,推荐。
本书以图配文的形式,直观易懂地详细介绍了面向对象的全貌及其中包含的各项技术,包括面向对象编程、框架、设计模式、UML、建模、面向对象设计和敏捷开发等。对于各项技术是如何使用的(How),书中只进行最小限度的说明,而重点介绍这些技术究竟是什么样的(What)以及为什么需要这些技术(Why)。另外,书中设有“编程往事”专栏,介绍了作者年轻时的一些经历;还设有“对象的另一面”专栏,以与正文不同的视角讲解面向对象这一概念普及的背景和原因,通俗有趣。
图灵官方小店
享受正版低价折扣