小说读一读,强烈建议每一个想成功的程序员读一读此文章

强烈建议每一个想成功的程序员读一读此文章 - 应用软件 - 电脑教程网

强烈建议每一个想成功的程序员读一读此文章

日期:2006-11-29   荐:
好的开始是成功的一半,本书首先会试图告诉你什么是程序员?为什么要做这样的程序?正确的入门方法是什么?
程序员只有在理解了以上内容的基础上,才能进一步更快地提高自身技能,这时候再开始程序的设计。其实,对一个软件的开发者来说,真正重要的不在于这行代码怎么写,那些代码应该怎么写,关键是思路的问题,而思路事实上是经验的积累。经验是使你从最初的封闭的思维方式,到最后形成开放式的思维的一个过程。将我十几年程序生涯中获得的一些经验告诉读者,使大家少走弯路也是我想写这本书的主要目的。

1.1 程序≠软件
现在很多人以为程序就是软件,软件就是程序。事实上,软件和程序在20世纪80年代时,还可以说是等同的,或者说,在非PC领域里它们可能还会是等同的,比如说某个嵌入式软件领域,软件和程序可能是等同的。但是,在PC这个领域内,现在的程序已不等于软件了。这是什么意思呢?
1. 软件发展简述
在20世纪80年代的时候,PC刚诞生,这时国内还没有几个人会写程序。那么,如果你写个程序,别人就可以拿来用。这时候的程序就能产生价值,这个程序就直接等同于软件。
但软件行业发展到现在,这里以中国的情况为例(美国在20世纪80年代,程序已经不等同于软件了),程序也不等同于软件了。因为现在会写程序很容易,但是你的这个程序很难产生什么样的商业意义,也不能产生什么价值,这就很难直接变成软件。要使一个程序直接变成软件,中间就面临着很高的门槛问题。这个门槛问题来自于整个行业的形成。
现在,你写了一个程序以后,要面临商业化的过程。你要宣传,你要让用户知道,你要建立经销渠道,可能你还要花很多的时间去说服别人用你的东西。这是程序到软件的一个过程。这门槛已比较高了。
我们在和国内的大经销商的销售渠道的人聊天时,他们的老板说,这几年做软件的门槛挺高的,如果你没有五、六百万做软件,那是“玩”不起来的。我说:“你们就使门槛很高了。”他说:“那肯定是的。如果你写个“烂”程序,明天你倒闭了,你的东西还占了我的库房,我还不知道找谁退去呢。我的库房是要钱的呀!现在的软件又是那么多!”
所以,如果你没有一定的资产的话,经销商都不理你。实际情况也是这样的,如果你的公司比较小,且没什么名气,你的产品放到经销商库房,那么他最多给你暂收,产品销不动的话,一般两周绝对会退货。因为现在经销商可选择的余地已很多了,所谓的软件也已经很多了。而程序则更多,程序都想变成软件,谁都说自己的是“金子”。但只有经受住用户的检验,才能成为真正的“金子”。
这就是美国为什么在20世纪90年代几乎没有什么新的软件公司产生的原因。只是原来80年代的大的软件公司互相兼并,我吞你,你吃我。但是,写程序的人很多,美国的程序变软件的门槛可能比我们还高,所以很多人写了程序就丢在网上,就形成了共享软件。
2. 共享软件
共享软件是避开商业渠道的一种方法。它避开了商业的门槛,因为这个行业的门槛发展很高以后就轻易进不去了。我写个程序丢在网上,你下载就可以用,这时候程序又等于软件。共享软件是这样产生的,是因为没有办法中的办法。如果说程序直接等于软件的话,谁也不会轻易把程序丢到网上去。
开始做共享软件的人并不认为做它能赚钱,只是后来用的人多了,有人付钱给他了。共享软件使得程序和软件的距离缩短了,但是它与商业软件的距离会进一步拉大。商业软件的功能和所要达到的目标就不是一个人能“玩”得起来的了。这时的软件也已不是几个人、一个小组就能做出来的了。这就是在美国新的软件公司没法产生的原因。比如Netscape网景是在1995~1996年产生的新软件公司,但是,两三年后它就不见了。
1.1.1 商业软件门槛的形成
1. 商业软件门槛的形成
商业软件门槛的形成是整个行业发展的必然结果。任何一个行业初始阶段时的门槛都非常低,但是,只要发展到一定的阶段后,它的门槛就必然抬高。比如,现在国内生产小汽车很困难,但在20世纪50年代~60年代的时候,你装4个轮子,再加上柴油机等就形成汽车。那时的莱特兄弟装个螺旋桨,加两个机翼,就能做飞机。整个行业还没有形成的时候,绝对可以这样做,但是,到整个行业形成时,你就做不了了。所有的行业都是这样的。
为什么网站一出来时那么多人去挤着做?这也是因为一开始的时候,看起来门槛非常低,人人都可以做。只要有一个服务器,架根网线,就能做网站。这个行业处于初始阶段时,情况就是这样的。但这个行业形成后,你就轻易地“玩”不了了。
国内的软件发展也是如此。国内的软件自从软件经销商形成以后,这个行业才真正地形成。有没有一个渠道是判断一个行业是否形成的很重要的环节。任何一个行业都会有一个经销渠道,如果渠道形成了,那么这个行业也就形成了。第一名的经销商是1994年~1995年成立的,也就是说,中国软件行业大概也就是在1995年形成的,至今才经历8年时间的发展。
有一种浮躁的思想认为,中国软件产业应该很快就能赶上美国。美国软件行业是上世纪80年代形成的,到现在已经发展了20多年了。中国软件行业才8年,8年才是一个懵懂的小孩,20多岁是一个强壮的青年,那么他们的力量是不对等的。但也要看到,当8岁变成15岁的时候,它真正的能量才会反映出来。
2. 软件门槛对程序员的影响
现在中国软件行业正在形成。所以,现在做一个程序员一定要有耐心,因为现在已经不等于以前了。你一定要把所有的问题搞清楚,然后再去做程序。
对于程序员来说,最好的工作环境是在现有的或者初始要成立的公司里面,这是最容易成功的。个人单枪匹马闯天下已经很困难了。即使现在偶尔做两个共享软件放在网上能成名,但是也已经比较困难了。因为现在做软件的人已经很多了。这也说明软件已经不等于程序了,程序也不等于软件。
程序要变成软件,这中间是一个商业化的过程。没有门槛以前,它没有这个商业过程,现在有这个行业了,它中间就有商业化的过程。这个商业的过程就不是一个人能“玩”的。
如果你开始做某一类软件的时候,别人已经做成了,这时你再决定花力气去做,那么你就要花双倍的力气去赶上别人。
现在的商业软件往往是由很多模块组成的,模块是整个系统的一部分。个人要完整地写一个商业系统几乎是不可能的。软件进入Windows平台后,它已经很复杂了,不像在DOS的时候,你写两行程序就能卖,做个ZIP也能卖。事实上,美国的商业编译器也不是一个人能“玩”的。现在你可能觉得它是很简单的,甚至Linux还带了一个GCC,且源程序还在。你可以把它改一改,做个VC试一试,看它会有人用吗?它能变成软件吗?即使你再做个界面,它也还是一个GCC,绝对不会成为Visual C 那样能商业化的软件。
可见,国外软件行业的门槛要比中国的高很多了。我觉得我们中国即使再去做这样的东西,也没有多大的意义了。这个门槛你是追不过来的。不仅要花双倍的力气,而且在这么短的时间内,你还要完成别人已经完成过的工作,包括别人所做的测试工作。只有这样,才能做到你的软件与别人有竞争力,能与它做比较。
1.1.2 认清自己的发展
如果连以上认识都不清楚,很可能就以为去书店买一本MFC高手速成之类的书,编两个程序就能成为软件高手。就好像这些书是“黄金”,我学两下,学会了VC、MFC,就能做一个软件拿出去卖了。这种想法也不是不行,最后一定能行,但要有耐心,还要有机遇。机遇是从耐心中产生的,越有耐心,就越有机遇。你得非常努力,要花很多的精力,可能还要走很多的弯路。
如果你是从MFC入手的,或是从VB入手的,则如要做出一个真正的能应用个人领域的通用软件,就会走非常多的弯路。直接的捷径绝对不是走这两条路。这两条路看起来很快,而且在很多公司里面确实需要这样的东西,比如说我这家公司就是为另一个家公司做系统集成的,那我就需要这样的东西,我不管你具体怎么实现,我只需要达到这个目标就行了。
任何软件的实现都会有n种方法,即使你是用最差的那种方法实现的,也没有问题,最后它还是能运行。即使有问题,再改一改就是。但是,做通用软件就不行了,通用是一对多,你做出来的软件以后要面向全国,如果将来自由贸易通到香港也好,通到国外也好,整个产品能销到全世界的话,这时候,通用软件所有做的工作就不是这么简单了。所以说,正确的入门方法就很关键。
如果你仅仅只是想混口饭吃,找个工作,可能教你成为MFC的高手之类的书对你就足够了。但是,如果你想做一个很好的软件,不仅能满足你谋一碗饭吃,还能使你扬名,最后你的软件还能成为很多人用,甚至你还想把它作为一个事业去经营,那么这第一步就非常关键。这时就绝对不能找一本MFC或找一本VB的书学两下就行,而是要从最底层开始做起,从最基本做起。

1.2 高手是怎样练成的
1.2.1 高手成长的六个阶段
程序员怎样才能达到编程的最高境界?最高境界绝对不是你去编两行代码,或者是几分钟能写几行代码,或者是用什么所谓的可视化工具产生最少的代码这些工作,这都不是真正的高手境界。即使是这样的高手,那也都是无知者的自封。
我认为,一个程序员的成长可分为如下六个阶段。
 第一阶段
此阶段主要是能熟练地使用某种语言。这就相当于练武中的套路和架式这些表面的东西。
 第二阶段
此阶段能精通基于某种平台的接口(例如我们现在常用的Win 32的API函数)以及所对应语言的自身的库函数。到达这个阶段后,也就相当于可以进行真实散打对练了,可以真正地在实践中做些应用。
 第三阶段
此阶段能深入地了解某个平台系统的底层,已经具有了初级的内功的能力,也就是“手中有剑,心中无剑”。
 第四阶级
此阶段能直接在平台上进行比较深层次的开发。基本上,能达到这个层次就可以说是进入了高层次。这时进入了高级内功的修炼。比如能进行VxD或操作系统的内核的修改。
这时已经不再有语言的束缚,语言只是一种工具,即使要用自己不会的语言进行开发,也只是简单地熟悉一下,就手到擒来,完全不像是第一阶段的时候学习语言的那种情况。一般来说,从第三阶段过渡到第四阶段是比较困难的。为什么会难呢?这就是因为很多人的思想变不过来。
 第五阶级
此阶段就已经不再局限于简单的技术上的问题了,而是能从全局上把握和设计一个比较大的系统体系结构,从内核到外层界面。可以说是“手中无剑,心中有剑”。到了这个阶段以后,能对市面上的任何软件进行剖析,并能按自己的要求进行设计,就算是MS Word这样的大型软件,只要有充足的时间,也一定会设计出来。
 第六阶级
此阶段也是最高的境界,达到“无招胜有招”。这时候,任何问题就纯粹变成了一个思路的问题,不是用什么代码就能表示的。也就是“手中无剑,心中也无剑”。
此时,对于练功的人来说,他已不用再去学什么少林拳,只是在旁看一下少林拳的对战,就能把此拳拿来就用。这就是真正的大师级的人物。这时,Win 32或Linux在你眼里是没有什么差别的。
每一个阶段再向上发展时都要按一定的方法。第一、第二个阶段通过自学就可以完成,只要多用心去研究,耐心地去学习。
要想从第二个阶段过渡到第三个阶段,就要有一个好的学习环境。例如有一个高手带领或公司里有一个好的练手环境。经过二、三年的积累就能达到第三个阶段。但是,有些人到达第三个阶段后,常常就很难有境界上的突破了。他们这时会产生一种观念,认为软件无非如此,认为自己已无所不能。其实,这时如果遇到大的或难些的软件,他们往往还是无从下手。
现在我们国家大部分程序员都是在第二、三级之间。他们大多都是通过自学成才的,不过这样的程序员一般在软件公司也能独当一面,完成一些软件的模块。
但是,也还有一大堆处在第一阶段的程序员,他们一般就能玩玩VB,做程序时,去找一堆控件集成一个软件。
现在一种流行的说法是,中国软件人才现在是一个橄榄型的人才结构,有大量的中等水平的程序员,而初级和高级程序员比较少。而我认为,现在中国绝大多数都是初级的程序员,中级程序员很少,高级的就更少了。所以,现在的人才结构是“方塔”形,这是一种断层的不良结构。而真正成熟的软件人才结构应该是平滑的三角形结构。这样,初级、中级、高级程序员才能充分地各施所长。三种人才结构对比如图1.1所示。


图1.1 三种人才结构对比
1.2.2 初级程序员和高级程序员的区别
一般对于一个问题,初级程序员和高级程序员考虑这个问题的方法绝对是不同的。比如,在初级程序员阶段时,他会觉得VB也能做出应用来,且看起来也不错。
但到了中级程序员时,他可能就不会选择VB了,可能会用MFC,这时,也能做出效果不错的程序。
到高级程序员时,他绝对不是首先选择以上工具,VB也好,VC也好,这些都不是他考虑的问题。这时考虑的绝对是什么才是具有最快效率、最稳定性能的解决问题的方法。
软件和别的产品不同。比如,在软件中要达到某个目标,有n种方法,但是在n种方法中,只有一种方法或两种方法是最好的,其他的都很次。所以,要做一个好的系统,是很需要耐心的。如果没有耐心,就不会有细活,有细活的东西才是好东西。我觉得做软件是这样,做任何事情也是这样的,一定要投入。

程序员到达最高境界的时候,想的就是“我就是程序,程序就是我”。这时候我要做一个软件,不会有自己主观的思路,而是以机器的思路来考虑问题,也就是说,就是以程序的思考方式来思考程序,而不是以我去设计程序的方式去思考程序。这一点如果不到比较高的层次是不能明白的。
你设计程序不就是你思考问题,然后按自己的思路去做程序吗?
其实不是的。在我设计这个程序的时候,相当于我“钻”入这个程序里面去了。这时候没有我自己的任何思维,我的所有思维都是这个程序,它这步该怎么走,下步该怎么走,它可能会出现什么情况。我动这个部分的时候,别的部分是否要干扰,也许会动一发而牵全身,它们之间是怎么相互影响的?
也只有到达这个境界,你的程序才能真正地写好,绝对不是做个什么可视化。可视化本身就是“我去设计这个程序”,而真正的程序高手是“我就是程序”,这两种方法绝对是不同的。比如,我要用VB去设计一个程序,和我本身就是一个程序的思维方式,是不一样的。别人也许觉得操作系统很深奥,很复杂,其实,如果你到达高手状态,你就是操作系统,你就能做任何程序。
对待软件要有一个全面的分析方法,光说理论是没有用的。如果你没有经过第一、第二、第三、第四这四个阶段,则永远到达不了高境界。因为空中楼阁的理论没有用,而这些必须是一步一步地去做出来。
一个高级程序员应该具备开放性思维,从里到外的所有的知识都能了解。然后,看到世界最新技术就能马上掌握,马上了解。实际上,技术到达最高的境界后,是没有分别的。任何东西都是相通的,只要你到达这个境界以后,什么问题一看就能明白,一看就能抓住最核心的问题,最根本的根本,而不会被其他的枝叶或表象所迷惑,做到这一步后才算比较成功。
从程序员本身来说,如果它到达这一步以后,他就已经形成了开阔的思维。他有这种开放性思维的话,他就能做战略决策,这对他将来做任何事情都有好处。事实上,会做程序后,就会有一种分析问题的方法,学会怎么样把问题的表象剖开,看到它的本质。这时你碰到任何具体的问题,只要给点时间,都能轻而易举地解决。实际上,对开发计算机软件来说,没有什么做不了的软件,所有的软件都能做,只是看你有没有时间,有没有耐心,有没有资金做支撑。
这几年,尤其是这两三年,估计到2005年前,中国软件这个行业里面大的软件公司就能形成。现在就已经在形成,例如用友,它上市后,地位就更加稳固了。其他大的软件企业会在这几年内迅速长大。这时候,包括流通渠道、经销商的渠道也会迅速长大。也就是说,到2005年以后,中国软件这个行业的门槛比现在还要高很多,与美国不会有太大的差别。此时,中国软件才真正体现出它的威力来。如果你是这些威力中的一员,就已经很厉害了。
别人可能知道比尔•盖茨是个谈判的高手,是卖东西的高手,其实,比尔•盖茨从根本上来说是个程序高手,这是他根本中的根本。他对所有的技术都非常敏感,一眼就看到本质,而且他本身也能做程序,时常在看程序。现在他不做董事长,而做首席设计师,这时他就更加接近程序的本质。因为他本身就有很开阔的思维,又深入到技术的本身,所以他就知道技术的方向。这对于一个公司,对他这样的人来说,是非常重要的。
如果他判断错误一步,那公司以后再回头就很难了。计算机的竞争是非常激烈的,不能走错半步。很多公司以前看上去很火,后来就
销声匿迹了,就是因为它走错一步,然后就不行了。为什么它会走错?因为他不了解技术的本质在哪里,技术的发展方向在哪里。
比尔•盖茨因为父母是学法律的,所以他本身就很能“侃”,很有说服力,而他又是做技术的,就非常清楚技术的方向在哪里,所以他才能把方向把握得很准确,公司越来越大。而别的公司只火一阵子,他却火了还会再火。就算微软再庞大,你如果不把握好软件技术的最前沿,一样也会玩完。就像Intel时刻把握着CPU的最新技术,才能保证自己是行业老大。技术决定它的将来。

所以,程序员要能达到这样的目标,就要有非常强的耐心和非常好的机遇才有可能。事实上,现在的机会挺好的,2005年以前机会都非常大,以后机会会比较小。但是,如果有耐心的话,你还是会有机会的,机会都是出在耐心里。我记得有句话说“雄心的一半是耐心”,我认为雄心的三分之二都是耐心。如果你越有野心,你就越要有耐心,你的野心才有可能实现。如果你有野心而没有耐心,那都是胡思乱想,别人一眼就能看穿。最后在竞争中,对手一眼就看到你的意图,那你还有什么可竞争的?


1.2.3 程序员是吃青春饭的吗
很多人都认为程序员是三十岁以前的职业,到了三十岁以后,就不应再做程序员了。现在的很多程序员也有这种想法,我觉得这种想法很不对。
在20世纪80年代末到90年代初,那时软件还没有形成行业,程序员不能以此作为谋生的手段时,你必须转行,因为你年轻的时候不用考虑吃饭的问题,天天“玩”都可以,但是以后就不可能了。
据我了解,微软里面的那些高手,几乎都是四五十岁的,而且都是做底层的。他们是上世纪70年代就开始“玩”程序的,所以对于整个计算机,他们是太清楚了。现在有些人主观臆断地希望微软第二天倒闭就好了,但那可能性太小了。因为那些程序员是从CPU是4004的时候开始,玩到现在奔腾IV,没有哪一代东西他们没有经历过。
你知道他们现在正在玩什么吗?现在正在玩64位的CPU。你说你普通的程序员,有这个耐心吗?没有这个耐心,你绝对做不了,你也绝对做不了高手。他为什么能做?因为他不仅是玩过来的,而且他还非常有耐心,每一步技术他都跟得上,所以对他来说,没有任何的难度和压力。
因为计算机技术没有任何时候是突变的。它的今年和去年相差不会很大,但是回过头来看三年以前的情况,和现在的距离就很大。所以说,如果你每年都跟着技术进步的话,你的压力就很小,因为你时刻都能掌握最新的技术。但是,如果你落下来,别说十年,就是三年,你就赶不上了。
如果你一旦赶不上,就会觉得非常吃力;如果你赶不上,你就会迷失方向;如果你迷失了方向,你就觉得计算机没有味道,越做越没劲。当你还只是有个思路的时候,别人的产品都做出来了,因为你的水平跟别人相差太远,人家早就想到的问题,你现在才开始认识。水平越高,他就看得越远,那么他的思维就越开阔;水平越低,想的问题就越窄。
64位CPU是这个十年和下个十年最重要的技术之一,谁抓住这个机会,谁就能抓住未来赚钱的商机。CPU是英特尔设计的,对这一点他肯定清楚。举例来说,如果从64位的角度来看现在的32位,就像从现在的角度去看DOS。你说DOS很复杂吗?当你在DOS年代的时候,你会觉得DOS很复杂。你说现在的Windows不够复杂吗?Windows太复杂了,但是你到了64位的时候再去看Windows,就如同现在看DOS一样。
整个64位系统的平台和思维方式、思路都比现在更开阔,打个比方说,现在的Windows里面能开n个DOS窗口,每个DOS窗都能运行一个程序。到达64位的时候,操作系统事实上能做到开n个X86,开n个Windows 98,然后再开n个Windows 95都没有问题,系统能做到这一步,甚至你的系统内开n个Windows NT都没有关系。这就是64位和32位的差别。所以,微软的那些“老头”,四、五十岁的那几个做核心的人,现在正在玩这些东西。你说微软的技术它能不先进吗?是Linux那几个玩家能搞定的吗?
微软的技术非常雄厚,世界计算机的最新技术绝对集中在这几个人手里。而且这几个人的思维模式非常开阔,谁都没有意识到的东西他早就开始做了。现在64位的CPU都出来一二年了,你说有什么人去做这些应用吗?没有,有的就是那几个UNIX厂商做好后给自己用的。

所以,追求技术的最高境界的时候,实际上是没有年龄限制的。对我来说,现在都三十三了,我从来没有想过退出这行,我觉得我就能玩下去,一直玩到退休都没有问题。我要时刻保持技术的最前端,这样的话对我来说是不困难的,没有任何累的感觉。
很多人说做程序不是人干的事情,是非人的待遇。这样,他们一旦成立一个公司,做出一点成绩,在辉煌的时候马上就考虑退出。因为他们太苦了,每天晚上熬夜,每天晚上烧了两包烟还不够,屋子里面简直就缺氧了,好像还没有解决问题。
白天睡觉,晚上干活,那当然累死了,这是自己折腾自己。所以,做程序员一定要有一种正常的心态,就是说,你做程序的时候,不要把自己的生活搞得颠三倒四的。如果非得搞得晚上烧好多烟才行,这样你肯定折腾不到三十岁,三十岁以后身体就差了。
事实上,我基本上就没有因为做程序而熬夜的。我只经历过三次熬夜,一次是在学校的时候,1986年刚接触计算机时,一天晚上跟一个同桌在计算机室内玩游戏,研究了半天,搞着搞着就到了天亮,这是第一次。然后在毕业之前,在286上做一个程序。还有一次就是超级解霸上市前,那时公司已吹得很大了,那天晚上没法睡觉。
一般来说,我也是十二点钟睡觉,第二天七点就起了。所以说,只有具有正常的生活、正常的节奏,才有正常的心态来做程序员,这样,你的思路才是正常的,只有正常的东西才能长久。搞疲劳战或者是黑白颠倒,时间长久后就玩不转了,玩着玩着就不想玩了。


1.3 正确的入门方法
在这一节中,主要讲从我的经验来看,一般程序员需要注意的地方。教你怎样去具体学习不是我的责任,你可以去任何一个书店去找一本书回来自己看就可以了。这里只是对这些书做一些补充以及一些平常从来没注意的内容。
入门最基本的方法就是从C语言入手。如果以前学过BASIC语言的话,那么从C语言入手是非常容易的。我就经历了一个过程,根本不觉得这中间有太大的难度。其实,C语言本身和BASIC没有什么两样。BASIC每个所谓的命令在C语言里面都可以做成一个函数来实现,那么你就能用那个命令组合成整个程序。从这个角度来看,BASIC和C语言没有本质的差别。C语言就是入门的正确方法,没有其他。
现在的C语言本身就包含了嵌入汇编,使学习汇编语言的时候更加方便。你可以忽略掉纯汇编里面的很多操作。也许有人觉得这个方法太慢了。但要知道,工欲善其事,必先利其器,要想成功,没有一个艰苦的过程是不可能的,所以一开始的时候就要有耐心。如果你准备花5年的时间成为高手,那我敢说,你根本不用等到5年,你只要有这个耐心就足够了,你可能2年~3年内就能达到目标。但如果你想在一年时间内就成为高手,即使5年后,你还是成不了高手。
我们公司1998年招的开发人员都是应届大学毕业生。很明显,有人好像什么都会,又会CorelDraw,又会Photoshop,又会Flash,又会C++,甚至VB也会。可是这样的人到现在还是全都会,但是什么事情也做不好,做的东西“臭”死了。但其中有一个人就不同,他以前甚至连Windows的程序都没有做过,只会在DOS下做几个小程序。但当我们把超级解霸的程序给他看,让他去研究的时候,他只用一周的时间,就迅速掌握。他那个月进步非常快,几乎就是一生中进步最快的阶段,这就是一个质的飞跃。
从基本入手以后,当你的积累到达一个阶段以后,就会有一个质的飞跃的阶段。事实上,我也有这么一个阶段,这个阶段也是我离开大学以后,真正去公司做事的时候。当我真正拥有一台计算机后,我把所有以前积累的问题在一个月内做了探讨以后,感觉自己的水平迅速提高。

入门和积累是很重要的。事实上,到达高手的境界以后,不管什么语言不语言的,其实都根本不用去学,只要拿过来看两天,就全部精通。如果你没有入门,即使去书店找n本书,天天背它,你也不会成为高手。
所有的语言只是很花哨的表面东西。高手马上就能透过它的表象而看到它的本质。这样才是真正的高手。他不需要再去学什么Java,或者其他什么语言。当他真正要写个Java程序的时候,只要把Java程序拿过来看一看,瞄一瞄书,就全都清楚了。如果这时他学VB就更容易了,我想他不用一天的时间,就能学会。到达高手的境界以后,所有的事物都是触类旁通的。
当你成为C语言的高手,那么就你很容易进入到操作系统的平台里面去;当你进入到操作系统的平台里去实际做程序时,就会懂得进行调试;当你懂得调试的时候,你就会发现能轻而易举地了解整个平台的架构。这时候,计算机基本上一切都在你的掌握之中了,没有什么东西能逃得出你的手掌心。
上面只是针对程序的角度说明,另外一点也很重要,即好的程序员必须具备开放性思维,也就是思考问题的方法。程序员,尤其现在很多的程序员,都被误导从MFC入手,这就很容易形成一种封闭式的思维模式。这也是微软希望很多人只能学点表面的东西,不致成为高手,所以他大力推荐MFC之类的工具,但也真有很多人愿意去上他的当,最后真正迷失方向。说他做不了程序吧,他也能做程序,但是如果那个程序复杂一点,出现问题时,问题出在哪里就搞不清楚了,反正是不清楚。如果你真正有一种开放性的思维,在你能够成为高级程序员的时候,对MFC这些是不屑一顾的,MFC、VB根本不会在考虑的范围之内。
事实上很多人,包括外面很多公司里面工资挺高的人,可能一个月能拿五、六万的这些人,他们的思维也不一定能达到很高的境界。但是,他确实做了很多的事情,已经有很好的积累了。但要上升到更高的境界上,就要有正确的思维方法。这就是为什么比尔•盖茨说,他招人的时候宁愿招一个学物理,而不是学编程的。学物理的人会有非常非常广的思维,他考虑的小到粒子,大到宇宙,思维空间非常广阔,这样,他思考问题的时候,就会很有深度。
有人研究物理研究得比较深的时候,他能针对某个问题一直深入进去。很多写程序的人只会注意到这行代码或那行代码,则比较起来则显得肤浅。所以,编程的时候也要深入进去,把你的爱好、你的所有思维都放进去,努力做到物我合一的境界。


1.3.1 规范的格式是入门的基础
以前所有的C语言的书中,不太重视格式的问题,写的程序像一堆堆的垃圾一样。这也导致了现在的很多程序员的程序中有很多是废码、垃圾代码,这和那些入门的书非常有关系。因为这些书从不强调代码规范,而真正的商业程序绝对是规范的。你写的程序和他写的程序应该格式大致相同,否则谁也看不懂。如果写出来的代码大家都看不懂,那绝对是垃圾。如果把那些垃圾“翻”半天,勉强才能把里面“金子”找出来,那这样的程序不如不要,还不如重新写过,这样,思路还会更清楚一点。这是入门首先要注意的事情,即规范的格式是入门的基础。
1. 成对编码
正确的程序设计思路是成对编码,先写上面的大括号,然后马上写下面的大括号。这样一个函数体就已经形成了。它没有任何问题。然后,比如你要写个for循环,这时候先申明一个变量I,再写这个for循环。写上面的大括号,马上写下面的大括号,然后再在中间插一二行代码。插这段代码后,如果你又要用到新变量,则再在头上添加新的变量,然后再让它进行工作。这就是一种成对编码。
这样,当你用到一个内存的时候,写一个分配函数分配一块内存,马上就接着写释放这块内存的代码。然后你再在中间插上你要用这个内存做什么。这是正确的快速的编程方法。否则,你去查或调试代码都无从下手。针对这个程序来说,如果用成对编码,则它任何时候都是可以调试的,不需要你整个程序都写完后才能进行调试。
它是任何时候都可以编译调试的,甚至你写了两个大括号,中间什么也没有,它是空的时,你都可以进行调试。你写了第一个for循环,它也可以进行调试,当你又写了一个分配内存、释放内存以后,它还可以进行调试。它可以编译运行,里面可以放断点,这就是成对编码。
成对编码就涉及到代码规范的问题。为什么我说上面一个大括号,下面一个大括号,而不说成是前面一个大括号,后面一个大括号呢?如果是一般C语言的书,则它绝对说是后面加个大括号,回过头前面加个大括号。事实上,这就是垃圾程序的写法。正确的思路是写完行给它回车,给它大括号独立的一行,下面大括号也是独立的一行,而且这两个大括号跟那个for单词中间错开一个TAB。
集成环境的TAB首先要设成8,因为TAB的基本定义就是8,而现在的VC把它设成了4,这样使得你编出的程序放到一个标准的环境里看的时候就是乱的。
代码一定不能乱,一定要格式非常清楚,这点使你写的程序我能读,我写的程序你也能读,不需要再去习惯彼此的不同写法。
而且结合成对编码思维,这时候你去读一个程序的时候,你会发现,你读程序的方法变了。以前读程序的时候,你可以先去读它的变量是什么,然后再读第一行、第二行,读到最后一个大括号,这是一种读程序的方法。现在就不一样了,现在读程序的时候就养成了一种习惯,就是分块阅读程序,很明显两个大括号之间就是一块代码。
那么写出一个程序后,你要读这个程序是干什么的,只要看这个大括号和那个大括号之间的部分就可以了,不需要再去读其他的代码是干什么的。比如,你从Linux中或网上下载了一个“烂”程序后,该怎么去阅读它?最好的方法是先把程序所有的格式都整理好,先别去读它。把所有的格式按照这种规范化的方法,把它的括号全部整理好。这时候你再读那个程序,只要半分钟就读懂了,但是你可能要整理一个小时。但如果不这样做,你可能读两个小时都读不清楚该程序。
这点绝对不会有人告诉你,现在没有人去讲解这方面的技巧。这也是我写了那么多的程序,才总结出来的。一开始的时候,我也像那些教科书所教导那样写,后面放个大括号,前面放个大括号,甚至括号连括号,一连四个括号,每个括号对哪个最后都找不清楚。编译告诉你好像少了一个括号,于是找呀,找呀,上面找,下面找,而这个程序又很大,只有一个函数,上面在上屏,下面在下屏,最后翻来翻去也翻不出。
所以我就想,大括号之间要互相对应,即使不在一个屏幕内,也能很容易地看到它,因为只要光标落在这个大括号里面,往上去找,即能找到它头上的那个与此对正的,而且这些代码是在一起的。这一层代码和下一层代码是互相隔开的,我只要读这层代码,下面那一层代码就不需要了。
比如,它有n个for循环的时候,我只想看某一个for循环,这时我只要对正大括号,它的光标往上走,一下就能找到了。如果按照教科书那样写的话,你要读呀,读呀,要把所有的代码,把所有的for
循环都读一遍,才可能找到你要的东西。这就是成对编码和规范化的方法(详细叙述请参考代码规范一章)。

代码中如果不包括正确的思路,那该代码就没有什么用。如果是一个代码爱好者去收集代码,而现在网络上代码成群,Linux本身就带了一大堆的程序,那些程序对你真的有用吗?我看不见得。而且那些程序还在不断地升级,那程序还会有新版,如果你把它拿来看一下,对你来说其实没什么价值。
那怎么样使得它对你有用?就必须用上面所说的方法,经过这么处理以后,你就能真正取到它其中的设计思路,这样才能变废为宝。如果是MFC之类的东西,那你就不用找了,因为即使找,也找不出有价值的东西,全部是VC自动给你生成的一堆堆的垃圾框架,相对于网上Linux程序来说,它可能更“臭”一些。
在软件没有形成行业,程序等同于软件的时候,那时候程序很容易体现出价值来。只要得到代码,就相当于得到这个软件。但现在就不同了。现在的程序都不是几行,你写出的程序,如果又没有注释,格式又很乱,你拿过来给我,我还得花很长的时间才能读得清楚,那这样的程序的代码有价值吗?
我经常听到一些程序员在外面兜销代码,很多是学校的学生,尤其那些素质比较差的研究生,和老师做了一个项目后,他拿出来到外面到处去卖,但是他最后可能卖出去吗?最后可能还是没卖出去,因为那个程序很庞大。如果某个公司买了这个程序以后,该公司还得招一个人去读这个程序,当这个人读懂以后,他又离职了,那公司买这个代码干嘛?
2. 代码的注释
代码本身体现不出价值来,有价值的代码一定是不仅格式非常规范,而且还要有很详细的设计思路和注释,这个是很重要的。首先要养成这种习惯,教科书里面很少讲为什么要做注释,注释应该怎么注。有些人爱在哪儿下注释就在哪儿下注释,甚至在语句中间也加,中间也可弄两个斜杠放两个花括号写点注释。
注释格式是非常重要的,但很少有人去注意它。现在的程序如果没有注释,则基本上是没法用的,也就跟你拿一个可执行程序没什么两样,你拿过来还不能随便改,你改了后编出来的程序绝对不能用。所以,程序如果没有详细的注释,别人就算拿到了代码也没有用,体现不出它的价值来。
Linux是个操作系统,很厉害呀!其实那些程序你拿回来,耐心地去读它,会发现,它里面乱得很,那个内核程序除了作者自己能读懂外,别人可能要花很长的时间才能读懂。Apache的作者对自己Apache那套代码是很清楚,但换一个做浏览器的人去读,也会很困难。一般人只把代码复制下来后,打个BUILD命令看看能不能正确地编译,最后能正确编译的程序就是好的,如果不能正确编译的程序就删掉吧,再下载一个,因为他没有正确的对待代码的那种思维,而只是认为那代码本身才有很大的价值,不用关心有没有注释。
如果代码没有注释和规范,是没有价值的,这也是现在为什么很多的个人跑去卖源程序的时候,很多的公司都不要。我们不是说没有技术,任何程序都能做,只是时间的问题,而且像视频中有的技术,比那些卖代码的技术还要深得多。真正要做一个有价值的程序,开发程序的思维就很重要,这种思维的具体体现就在注释及规范的代码本身。


1.3.2 调试的重要性
调试是很重要的一个部分。所有的程序都是调试出来的,不是写出来的。讲怎么去调试,实际上就是讲一种解决问题的思路。所有的程序写出来后一定是有问题的,既然有问题,就一定会有一个解决问题的思路。解决问题的方法就是调试的方法。
用VB或者是MFC做出来的程序,先运行一遍看看什么地方有问题,如果发现有问题,重新改一改,然后又重新运行。这种方法是还没有入门的调试方法,即是看直接的表象。这种方法既浪费时间,又不能消除隐患。
调试是很重要的内容,如果要进入高深境界,调试是除了了解设计程序、平台以外,一个非常重要的难关。如果要成为高级程序员,就必须过这一关。如果不懂调试,则永远成不了高手。在学习调试的过程中,对汇编语言、体系结构会有进一步的了解。
你可能觉得我把调试的作用说得言过其实了,举例子说明一下吧。请把以下的C程序改写成汇编代码:
int i;
extern int In[],Out[];
for(i=0;i
这样的人不是没有,我是碰见过的。一些毕业生做的程序就有这种情况。所有的问题都由一个函数来解决。他就不会把它拆成几个模块。我问他,把一件工作拆成几件模块不是更清晰吗?他说,拆出来后的模块执行会更慢些。这就是很明显的封闭式思维和非封闭式思维的区别。
你看MFC的思路,那就是一层套一层的,要把所有的类都实现了,然后继承。它从CWnd以后,把所有的东西都包括进去了,组成一个巨型的类。这个巨型的类连界面到实现统统包括在里面。这时你怎么拆?根本就没有拆的方法,这就是封闭式思维。
如果一个系统、一个程序不能拆的话,则它基本上是做不好的。因为任何一个程序,如果它本身的复杂度越大,它可能出错的几率就越大。比如最简单的,哪个函数越大,则该函数的出错几率就越大。但如果把该函数分成很多小的函数,每个小的函数的出错几率就会很小,那么组合起来的整个程序的出错几率就很小。这就是为什么要把它拆出来的原因。
你用C 来实现的方法也是一样的。你要把它拆成许多的接口,如果能做到这样,你就能把它独立起来,甚至你能把它用动态库的方法去实现。动态库是现在的程序非常重要的一块。


1.4.1 动态库的重要性
有了动态库,当你要改进某一项功能的时候,你可以不动任何其他的地方,只要改其中你拆出来的这一块。这一块是一个动态库,然后把它改进,只需要把这个动态库调试好后,整个系统就可以进行升级。
但如果不是这样,你的整个程序是独立的文件,然后,另外的功能也是一个独立的文件,把这个程序编译成一个EXE,这就不是动态库的思想。按道理,我只改这个文件,其他系统也不需要进行调试。理论上看起来是一样的,而实际的结果往往就是因为你改动了这个文件,使得原来跑得很好的整个系统,现在不能跑了或者出现了很奇怪的现象。如何解释这个问题?事实上,这就涉及到编译器产生代码的方法,如果不了解这点的话,永远找不出问题来。
不存在没有BUG的编译器,包括VC,它也会产生编译上的问题。就算把这些问题都排除,你的软件也可能因为你加了某些功能,而影响了其他的文件,这个几率甚至非常大。这又得把你以前的测试工作重头再来一遍了。
动态库和EXE有什么不同呢?
动态库,包括它的代码和数据都是独立的,绝对不会跟其他的动态库串在一起。但是,如果你把所有功能放到一个EXE的工程里面,它的数据和代码就都是放到一起的,最后产生可执行程序的时候,就会互相干扰。而动态库就不会,这是由操作系统来保证的。从理论上看,动态库也是一个文件,我做这个工程的时候也是一个独立的文件,但它就会出现这样的问题。
1.4.2 程序设计流程
程序设计流程其实很简单。第一步就是要拆出模块,如果你有开放性思维,则任何软件都非常容易设计。怎么设计呢?首先,拿到问题的时候,一定要明确目标;然后,对操作系统所提供哪些功能,程序怎么跟操作系统接口考虑清楚;接着,就是“砍”,把它分开,要把它拆成一个个的独立的模块;最后,再进一步去实现,从小到大地进行设计。
首先“抓”马上能进行测试的简单的模块,就像刚才说的成对编码那样,写任何一个部分都要进行调试,每个部分最好能独立进行调试。这样,每个部分都是分开的时候,它都有一定的功能。当把所要做的功能都实现后,组合起来,再进行通调就可以了。
决定一个软件的成败还是得看该软件设计的思维是否正确。我们也试过,即使你把那些所谓的软件写得再明白也没有用,如果实现这个软件的思路不对,则下面的工作根本就没有必要。
做软件时,一定要把注释写进去。这样写成的软件如果要改版的话,就很容易,因为你的整个系统是开放性的,那么你要增强某些功能的时候,都是针对其中的某个小项做改进,只要改它就是了。如果那个功能是全新的,则它本身就是一个独立块,只要去做即可。
现在很多开发工具都提供了自动化设计的功能,在生成新的程序的时候,只要设置好一些条件,就能自动产生程序的框架,这是一种趋势吗?
其实,这种方法不太适用通用软件的开发,针对某个公司做个ERP系统,可能会管用,但是那些方法拿不到通用软件里面来。通用软件绝对是一行一行地编码产生出来的,而且每一行编码的结果要达到一种可预测性。
什么叫可预测性?就是你写程序的时候,如果发现某一种症状,马上就能想到该症状是由于哪个地方出了错,而不是别的地方,也就是从症状就能判断出是哪些代码产生了问题,这就是可预测性。
如果你用MFC来“玩”的话,即使它出错了,你也可能不知道错误在哪里,它的可预测性就很差。做软件时,如果它的可预测性越高,解决问题的方法就越快。如果某用户说我出现什么状况了,你马上就可以断定错误,而不用去搜索源代码,就能想到程序可能是什么地方有问题,则这就是可预测性。
1.4.3 保证程序可预测性
设计程序的时候,如何保证可预测性呢?答案就是我们上面所说的,所有的代码必须是经过测试的,必须是一步一步调试过的。只有经过你调试过的代码,你才能知道这个代码做某种运算的时候,它是怎样的执行方法。如果你不知道它的执行方法,你没进行过调试,则你就没有任何预测性。要达到可预测性,代码在汇编级是怎么执行的,你都得非常清楚。代码对哪个部分进行了什么操作,你都得知道。如果达不到这点,你的可预测性就很差。
比如,有些程序,你看它的C或者C 的源代码时,都看不出任何的问题。你看静态的程序时看不出任何问题,动态的程序调试你也看不出任何问题,这时,你必须把它的汇编打开,看一看它具体的操作,才能知道。所以说,开放性思维非常重要,你必须从最低层到最上层都要清楚。VC本身提供了一个汇编的调试环境,但是打开汇编后,如果你都看不懂,那你说怎么调呢?调什么?如果一个程序经过调试出来,则它会出错的地方你马上就会知道,只要看一些表现,就知道它有些什么问题。
比如说,我们做“大眼睛”的时候有个这样的现象。当要显示一个很大的图的时候,屏幕上只能显示其中的一小块,这样就可能需要拖动整个图像,但是拖的时候,如果在Windows 2000或Windows XP系统下就会发现,一旦我将图像拖到右下角时,图像就一下到左上角去了。该图像在右下角没有到底的时候还是显示正确的,但一旦到底,就把右下角转到左上角去了,如图1.2所示。
这是怎么回事?在Windows 98和Windows 95下,从来没有这个问题,而且如果图像不到右下角这一行,只差一点,它也不会出现这样的问题。为什么在Windows 98下没有这样的问题,在Windows 2000下会有呢?难道是我的程序有问题?

图1.2 图像显示问题示意图
这时,我就做了一个区域的比较,即看这个区域和整个这个图像的区域,是否中间运算有错误。但程序是调用Windows本身的API,我就怀疑是不是这个API出问题了。于是又重新写了一个区域相交部分,一步一步去查它,也没有任何问题,在任何情况下都是好的,但是到达右下角时,图像就会翻过来。经过以上两个步骤后,我就能确定,这是Windows操作系统的问题,Windows 98下没有这个问题,Windows 2000有,Windows XP也没有改过来。这是操作系统的原因,绝对不是软件的问题。
为什么会出现这样的问题?这是因为微软设计系统的那些家伙自以为聪明。只要图像的左上角是0,不管三七二十一,肯定往下面放,但是它的图像是正向位图,所有的位图设计的时候是倒过来的。而一个正向位图的高度是负的,否则它显示的时候是倒过来的。高度是负的时候,这个0发生了变化,从上向下的,那么他设计操作系统的时候,只看了0而没去看高度,这时他没做条件处理。他的想法是为了加速这个位图的速度,是做优化的结果,但结果就出错了,而到现在他也没有解决这个问题。
所以,可预测性在这里就显得很重要了。当出现这个问题时,能想到要么就是区域合并有问题,要么就是直接显示的这个函数有问题。区域合并的问题可以解决,我写个函数还不行吗?我一步一步地去跟踪,就能肯定这个API有没有问题,最后得出结论是有问题,也的确是它有问题。如果你不会调试的话,这个问题你永远也查不出来;如果你不了解操作系统,你永远不会想到操作系统会出问题;如果你不了解这个平台,你根本就不知道问题所在。所以,要成为一个高手,视角一定要从里到外,从点到面非常开阔。
标签: