透过概念看到本质
记得高中候最开始学习写程序的时候,都是实现一些很简单的功能,读入输入、处理数据、输出结果,代码不过十几二十行,随着要实现的功能的复杂度上升,代码也越来越长,一个main函数上百行,若不是好好整理分段,那简直就是“面条”,这是老师说,要用结构化的方式编程。于是从书上学到了函数,把之前的分段代码都用函数分隔开,main函数里又变成了区区十几行代码,看起来井井有条,感觉漂亮多了。随着代码量越来越大,很多函数不止会调用一次,不同的情况下调用总有不同的变化。既然是函数就有参数,那么就用参数来表示这些不同和变化因素吧。于是就有了第一次的“复用”。
后来,代码量的增长,使函数调用的变化因素也越来越多,参数也越来越多,函数体对于各种不同情况处理也越来越复杂,有些函数内也出现了相似的代码。看着长长的参数列表和各种判断,实在是繁琐累赘。这是前辈说:“程序员要善于整理”。
也是把一个大函数再进行分解,成为了几个小函数,再重新组合完整的大函数的功能。整理完的代码,函数变小了,实现的逻辑变少了,但却因此更加灵活了,复用程度也提高了,代码又一次变的简洁美观。许多年后才知道,这算是做了一次“重构”。
经过几次的折腾,感觉自己的经验值够level up了,尝试这去写一个类似的Windows的窗口界面,结果发现,图形处理、逻辑判断、输入设备处理……函数实在是太多了,一个文件半天都翻不到底。好吧,C有include、Pascal有Use,比着葫芦画瓢,把做类似的事情的函数整理出来放到一个文件里,然后在主函数的文件中引用进来,代码又一次变短了。哦,这个原来就是传说中的“库”。
既然是库函数,那么自然要更加能够重复使用,尽量能够处理各种可能出现的情况。当库函数的代码也越来越多的时候,才发现要想让库函数处理各种情况几乎是不可能的,又出现了无法控制的不可知变化因素。翻遍了教科书,发现了函数指针。
这下好了,把这些库函数不可知的变化因素在实现中用一个函数指针代替,通过库函数的参数传进来,调用的时候再去实现具体该做什么,库函数只管调用传入的函数就好了。真正进入了Windows开发的年代才知道,这种函数指针的用法称作“回调函数”。
参数原来如此管用,函数实现中有什么可能变化的因素,就用一个参数来表示,不但能表示变化的值,还可以表示变化的代码,这样函数的复用性就好了。后来进入面向对象的年代时,之前所有折腾过的事情,和在一起就是“封装”。
当库函数越来越多,组织起来越来越复杂的时候,面向对象的思想出现了,许多概念也扑面而来,类、对象、封装、继承、多态、接口、耦合度、设计模式、控制反转、依赖注入等等。只是这时候所有这些概念看起来都很眼熟。类使我想起了库里的一个个文件,对象却像库函数被调用的样子,只是封装的程度更好些;看到多态的时候,不禁想起了函数指针,只是这回指针指向的时一个对象;看到接口的时候,我又想起了库函数头文件中的函数原型;看到设计模式时,满眼都是提取变化因素,也经常想起回调函数。
来到互联网和WEB时代,在CGI身上令人联想到printf(“hello word”);只是这回printf的时HTML;PHP、JSP、ASP,看到的依然时CGI的影子,只是这回多了一个模板文件挡在面前:配置文件,哦,这是写在文件里的函数参数。
之前由这些概念引起的联想,并非指两者可以直接划等号,也不可否认新技术带来的进步。但是不得不说的时,很多新名词和概念的本质,其实都是可以通过很简单的概念去理解的。又一次想起了之前一个技术初学者的困惑:“基础知识是否还有意义?”我想,对于那些短平快的想法去学习各种工具的初学者来说,如果有一点通过基础知识和编码实践得到的经验和理解作为基础的话,当面对现在和未来各种技术的时候,理解和看到他们的本质都不是一件难事。