要具备开放性思维,就必须了解包括从CPU的执行方法,到Windows平台的运转,到你的程序的调试,最后到你要实现的功能这一整套的内容,只有做到这样,才能真正提高。如果你的知识范围很窄,什么也不了解,纯粹只了解语言,那你的思维就会很狭隘,就会只想到这个语言有这个函数,那个语言没有那个函数,这个C++有这个类,那个语言没有这个类等。而真正要做一个系统,思维一定要是全面的,游离于平台之上的系统和实际的应用软件是不现实的。
这种所谓理想化,已经有很多人提出是不现实的。所以,任何一个软件一定都是跟一个平台相关联的,脱离平台之上的软件几乎都是不能用的。这就必须对平台的本身非常了解。如果你有平台这些方面的知识,这样在思考一个问题的时候,能马上想到操作系统能提供些什么功能,我再需要做些什么,然后就能达到这个目标。这就是一种开放的思维。
在开放的思维下,我要做这个程序的时候,就会考虑怎么把它拆成几个独立的、分开的模块,最简单的,怎么把这个模块尽量能单独调用,而不是我要做个很大的EXE程序。一个很普通的程序员,如果他能够考虑到将程序分成好几个动态库,那么它的思维就已经有点开放性了,就已经不是MFC那些思维方式了。思考问题的时候能把它拆开,就是说,任何一个问题,如果你能把它拆开来思考,这就是简单的开放性思维。
但光会拆还是不够的,尽管有很多人连拆都不会。很多教科书中的程序,要解决问题的时候,就一个main,以后就是一个非常长的函数。这个main函数把所有的事情都解决了。如果连函数都不会分的话,则就是典型的封闭式思维。
这样的人不是没有,我是碰见过的。一些毕业生做的程序就有这种情况。所有的问题都由一个函数来解决。他就不会把它拆成几个模块。我问他,把一件工作拆成几件模块不是更清晰吗?他说,拆出来后的模块执行会更慢些。这就是很明显的封闭式思维和非封闭式思维的区别。
你看MFC的思路,那就是一层套一层的,要把所有的类都实现了,然后继承。它从CWnd以后,把所有的东西都包括进去了,组成一个巨型的类。这个巨型的类连界面到实现统统包括在里面。这时你怎么拆?根本就没有拆的方法,这就是封闭式思维。
如果一个系统、一个程序不能拆的话,则它基本上是做不好的。因为任何一个程序,如果它本身的复杂度越大,它可能出错的几率就越大。比如最简单的,哪个函数越大,则该函数的出错几率就越大。但如果把该函数分成很多小的函数,每个小的函数的出错几率就会很小,那么组合起来的整个程序的出错几率就很小。这就是为什么要把它拆出来的原因。
你用C++来实现的方法也是一样的。你要把它拆成许多的接口,如果能做到这样,你就能把它独立起来,甚至你能把它用动态库的方法去实现。动态库是现在的程序非常重要的一块。
1.4.1 动态库的重要性
有了动态库,当你要改进某一项功能的时候,你可以不动任何其他的地方,只要改其中你拆出来的这一块。这一块是一个动态库,然后把它改进,只需要把这个动态库调试好后,整个系统就可以进行升级。
但如果不是这样,你的整个程序是独立的文件,然后,另外的功能也是一个独立的文件,把这个程序编译成一个EXE,这就不是动态库的思想。按道理,我只改这个文件,其他系统也不需要进行调试。理论上看起来是一样的,而实际的结果往往就是因为你改动了这个文件,使得原来跑得很好的整个系统,现在不能跑了或者出现了很奇怪的现象。如何解释这个问题?事实上,这就涉及到编译器产生代码的方法,如果不了解这点的话,永远找不出问题来。
不存在没有BUG的编译器,包括VC,它也会产生编译上的问题。就算把这些问题都排除,你的软件也可能因为你加了某些功能,而影响了其他的文件,这个几率甚至非常大。这又得把你以前的测试工作重头再来一遍了。
动态库,包括它的代码和数据都是独立的,绝对不会跟其他的动态库串在一起。但是,如果你把所有功能放到一个EXE的工程里面,它的数据和代码就都是放到一起的,最后产生可执行程序的时候,就会互相干扰。而动态库就不会,这是由操作系统来保证的。从理论上看,动态库也是一个文件,我做这个工程的时候也是一个独立的文件,但它就会出现这样的问题。
1.4.2 程序设计流程
程序设计流程其实很简单。第一步就是要拆出模块,如果你有开放性思维,则任何软件都非常容易设计。怎么设计呢?首先,拿到问题的时候,一定要明确目标;然后,对操作系统所提供哪些功能,程序怎么跟操作系统接口考虑清楚;接着,就是“砍”,把它分开,要把它拆成一个个的独立的模块;最后,再进一步去实现,从小到大地进行设计。
首先“抓”马上能进行测试的简单的模块,就像刚才说的成对编码那样,写任何一个部分都要进行调试,每个部分最好能独立进行调试。这样,每个部分都是分开的时候,它都有一定的功能。当把所要做的功能都实现后,组合起来,再进行通调就可以了。
决定一个软件的成败还是得看该软件设计的思维是否正确。我们也试过,即使你把那些所谓的软件写得再明白也没有用,如果实现这个软件的思路不对,则下面的工作根本就没有必要。
做软件时,一定要把注释写进去。这样写成的软件如果要改版的话,就很容易,因为你的整个系统是开放性的,那么你要增强某些功能的时候,都是针对其中的某个小项做改进,只要改它就是了。如果那个功能是全新的,则它本身就是一个独立块,只要去做即可。
现在很多开发工具都提供了自动化设计的功能,在生成新的程序的时候,只要设置好一些条件,就能自动产生程序的框架,这是一种趋势吗?
其实,这种方法不太适用通用软件的开发,针对某个公司做个ERP系统,可能会管用,但是那些方法拿不到通用软件里面来。通用软件绝对是一行一行地编码产生出来的,而且每一行编码的结果要达到一种可预测性。
什么叫可预测性?就是你写程序的时候,如果发现某一种症状,马上就能想到该症状是由于哪个地方出了错,而不是别的地方,也就是从症状就能判断出是哪些代码产生了问题,这就是可预测性。
如果你用MFC来“玩”的话,即使它出错了,你也可能不知道错误在哪里,它的可预测性就很差。做软件时,如果它的可预测性越高,解决问题的方法就越快。如果某用户说我出现什么状况了,你马上就可以断定错误,而不用去搜索源代码,就能想到程序可能是什么地方有问题,则这就是可预测性。
评论