RSS   



  可打印版本 | 推薦給朋友 | 訂閱主題 | 收藏主題 | 純文字版  


 


 
主題: [轉貼]編程高手箴言-學習程式開發的方法   字型大小:||| 
ROACH
版主
等級: 30等級: 30等級: 30等級: 30等級: 30等級: 30等級: 30等級: 30
減肥中!請勿餵食

十週年紀念徽章(四級)  

 . 積分: 15118
 . 精華: 14
 . 文章: 11766
 . 收花: 140844 支
 . 送花: 6005 支
 . 比例: 0.04
 . 在線: 8869 小時
 . 瀏覽: 85616 頁
 . 註冊: 7973
 . 失蹤: 3
 . 鄉下地方
#1 : 2005-3-7 12:17 AM     只看本作者 引言回覆

《編程高手箴言》

作者:梁肇新
連接位址:
http://www.huachu.com.cn/2003/csdn.htm#7

大陸近期出版的一本書,偶然看到上面的網站上有放上第一章‘程式點滴’,
感覺裏邊有些東西還可以參考一下、就把它貼了上來
第一章下載位址:
http://www.huachu.com.cn/images/temp/434.rar


第1章 程 序 點 滴

好的開始是成功的一半,本書首先會試圖告訴你什麼是程式師?為什麼要做這樣的程式?正確的入門方法是什麼?
程式師只有在理解了以上內容的基礎上,才能進一步更快地提高自身技能,這時候再開始程式的設計。其實,對一個軟體的開發者來說,真正重要的不在於這行代碼怎麼寫,那些代碼應該怎麼寫,關鍵是思路的問題,而思路事實上是經驗的積累。經驗是使你從最初的封閉的思維方式,到最後形成開放式的思維的一個過程。將我十幾年程式生涯中獲得的一些經驗告訴讀者,使大家少走彎路也是我想寫這本書的主要目的。
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<100;i++)
{
Out*=In;
}
我發現90%的人寫出來的彙編代碼可能是不正常的或有錯誤的。要麼是不瞭解32位彙編,要麼是不迴圈,要麼只有迴圈沒有處理等。這是為什麼呢?因為就算是一段小小的代碼,如果沒有經過調試,也可能錯誤百出。
如果你是初級一點的程式師,則如果程式出了問題,也不知道原因所在。怎麼回事呀?我就是搞不清楚。要搞清楚首先要調試,這就涉及到調試的問題。比如說,放到一個檔裏面的,它出錯了,我查程式看了n遍,它就是沒有任何問題,這時候該怎麼辦呢?這時的解決方法就是調試,調試能使得一個程式正常地運轉起來。如果對於程式師來說寫這個程式可能只用了一天的時間,但是調試可能會花他二三天的時間。一個程式絕對是調試出來的,不是編出來的。如果說哪個系統是編出來的,那它肯定會有很多性能方面的問題,包括可能有不可預測的各種各樣的問題。
程式出現問題的話,要能考慮到各種各樣可能的情況,絕對沒有任何臆測。比如,有可能完全是編譯器的錯誤,也有可能因你程式裏面增加了什麼,而對程式產生幹擾,甚至還有一種可能是你的指標基本就沒有給它賦值,指向了別的地方,把別的東西破壞了。這些情況太多了。還有一種常見的錯誤,即MFC裏面很常見的一種設計思維,就是任何一個東西,只管創建,不管釋放、銷毀。這種思路是現在很多程式師做的程式沒用幾下就會死機的原因。這絕對是錯誤的設計思路,而MFC讓你這麼做,就是讓你永遠成不了高手,你寫的程式永遠不可能穩定。
MFC裏面的所有的結構也好,變數也好,只需要你去分配一個,幾乎就不需要你去釋放它。這絕對是錯誤的,程式一定要成對編寫。成對編碼是快速編寫程式的一種方法,而教科書裏面講的那些都是從頭到尾去編。先把那個什麼變數編寫上,再寫第一行,再寫第二行,再寫第三行,最後再寫個大括弧。這種方法絕對是錯誤的。對於現在的程式來說,它效率很慢,沒法即時調試,因為只有最後把所有的程式做完以後,才能進行調試,所以在這中間出現錯誤的幾率就積累得非常大了。

1.4 開放性思維
要具備開放性思維,就必須瞭解包括從CPU的執行方法,到Windows平臺的運轉,到你的程式的調試,最後到你要實現的功能這一整套的內容,只有做到這樣,才能真正提高。如果你的知識範圍很窄,什麼也不瞭解,純粹只瞭解語言,那你的思維就會很狹隘,就會只想到這個語言有這個函數,那個語言沒有那個函數,這個C++有這個類,那個語言沒有這個類等。而真正要做一個系統,思維一定要是全面的,游離於平臺之上的系統和實際的應用軟體是不現實的。
這種所謂理想化,已經有很多人提出是不現實的。所以,任何一個軟體一定都是跟一個平臺相關聯的,脫離平臺之上的軟體幾乎都是不能用的。這就必須對平臺的本身非常瞭解。如果你有平臺這些方面的知識,這樣在思考一個問題的時候,能馬上想到作業系統能提供些什麼功能,我再需要做些什麼,然後就能達到這個目標。這就是一種開放的思維。
在開放的思維下,我要做這個程式的時候,就會考慮怎麼把它拆成幾個獨立的、分開的模組,最簡單的,怎麼把這個模組儘量能單獨調用,而不是我要做個很大的EXE程式。一個很普通的程式師,如果他能夠考慮到將程式分成好幾個動態庫,那麼它的思維就已經有點開放性了,就已經不是MFC那些思維方式了。思考問題的時候能把它拆開,就是說,任何一個問題,如果你能把它拆開來思考,這就是簡單的開放性思維。
但光會拆還是不夠的,儘管有很多人連拆都不會。很多教科書中的程式,要解決問題的時候,就一個main,以後就是一個非常長的函數。這個main函數把所有的事情都解決了。如果連函數都不會分的話,則就是典型的封閉式思維。
這樣的人不是沒有,我是碰見過的。一些畢業生做的程式就有這種情況。所有的問題都由一個函數來解決。他就不會把它拆成幾個模組。我問他,把一件工作拆成幾件模組不是更清晰嗎?他說,拆出來後的模組執行會更慢些。這就是很明顯的封閉式思維和非封閉式思維的區別。
你看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有沒有問題,最後得出結論是有問題,也的確是它有問題。如果你不會調試的話,這個問題你永遠也查不出來;如果你不瞭解作業系統,你永遠不會想到作業系統會出問題;如果你不瞭解這個平臺,你根本就不知道問題所在。所以,要成為一個高手,視角一定要從裏到外,從點到面非常開闊。如果你局限在一個封閉的思維裏,做系統就很難。



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  訪問主頁  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
南無
銀驢友〔高級〕
等級: 14等級: 14等級: 14等級: 14


今日心情

 . 積分: 996
 . 精華: 1
 . 文章: 5126
 . 收花: 6613 支
 . 送花: 5000 支
 . 比例: 0.76
 . 在線: 711 小時
 . 瀏覽: 54263 頁
 . 註冊: 7166
 . 失蹤: 87
#2 : 2005-3-7 10:59 PM     只看本作者 引言回覆

我最近買了這本書,目前研究中

第二章 認識CPU

第三章 WINDOWS執行原理

第四章 程式語言的執行原理

5章  程式碼的規範和風格

6章 分析方法

7章 除錯方法

8章 核心最佳化



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
jocosn
白銀驢友
等級: 15等級: 15等級: 15等級: 15等級: 15


今日心情

 . 積分: 1386
 . 精華: 2
 . 文章: 2945
 . 收花: 9537 支
 . 送花: 3671 支
 . 比例: 0.38
 . 在線: 1295 小時
 . 瀏覽: 19041 頁
 . 註冊: 7214
 . 失蹤: 1217
#3 : 2005-3-7 11:37 PM     只看本作者 引言回覆


引用:
南無寫到:
我最近買了這本書,目前研究中
....

這不是大陸出的書嗎?南無是大陸同胞啊?



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 7978
 . 失蹤: 5330
#4 : 2005-3-8 05:36 PM     只看本作者 引言回覆

@_@ 好長一篇... 真有耐心的敲...
覺得有些觀念似是而非... 不太會形容
我個人感覺是... 軟體抓錯... 真正憑借的是感覺
PC 上有很好的debug tool, 他可以去慢慢追
但是, 離開PC 的平台, 常常除錯是憑借感覺, 憑借自身對自己寫的程式的感覺, 然後只要能夠找出錯誤怎樣發生, 就自然知道錯誤發生在哪兒

當然... 這本書只是談"程式設計", so, 觀點總是由"人"出發
軟體是一個眾志成城的工作, 真正講究的, 根本不是怎樣去寫, 而是將來怎樣維護
思緒停留在程式怎樣寫, 那只是程式設計師等級的工作, 沒資格稱之為軟體工程師
軟體之所以稱之為"工程", 就是因為軟體的發展, 老早就進入需要採用"工程" 工法來設計的境界
程式語言從早期的非結構化 發展到講究結構化程式語言, 然後又從結構化程式語言進一步發展到物件導向化
這一路的發展, 都是配合軟體工程的需求, 講究的重點都是, 將來如何維護
其實寫程式很簡單, 在CPU 狂飆的境界下, 寫程式不會比吃飯喝湯困難
程式語言不斷演化, 都是著眼於維護, 維護一詞, 包含:
1. 新增功能時, 舊程式碼能盡量沿用
2. 有錯誤時, 能夠迅速解決且不引發新錯誤
3. 因應實際需要, 能快速修改符合需求
4. 開發新軟體時, 從前開發完成的資源能夠快速引用

曾經在另一篇文章中, 我有說到, C 跟C++ 的根本不同, 在於觀念, 而非語法, 其實就是上述原因.

C 是一個結構化程式語言, 寫一個C 的程式, 講究的是整個軟體工程如何模組化, 只要模組劃分的夠好, 所有參予者, 可以按照每個模組的定義, 獨立工作, 最後進行整合. 但是模組化觀念最終還是被淘汰, 因為, 模組定義常常不夠明確, 系統整合時才會發現出了問題, 其次, 模組在新開發案沿用過程, 難免需要修補, 造成重複使用過程需要耗費人力去維護/修改舊有模組

C++ 則是新的物件化觀念, 寫一個C++ 程式, 從物件著手, 先規劃出"好的物件", 然後才由這些物件去組合成對應模組, 進而變成一個軟體. 而物件化理論上比傳統結構化好的地方, 就是, 理論上, 一個"好的物件", 你可以不用理解他的細部結構, 你只要知道這個物件會完成怎樣行為, 就好了. 就好像你不用知道怎樣做一張桌子, 你會用桌子即可, 你不用會製造原子筆, 你只要會用就好了.

so, 一個C程式或者C++ 程式, 重點不是語法, 而是設計的出發點, 很多人用C++, 但是實際是在使用結構化程式設計的觀念, 這並沒有發揮C++ 的特性與優點. 這種程式, 我通常戲稱為, 只是穿著C++ 程式的外衣. 當然, Windows 環境中... 找不到"好的物件", MS 的MFC 是Windows platform 的標準application framework, 但是, 他卻是一個爛示範,  Borland 公司這方面是比較好的, 可惜, 那些人待錯公司, 他們當初為Windows 推出的application framework 是OWL, 從物件導向的觀點去看, OWL 的物件比MFC 好太多了, 但是, Windows 終究是MS 設計的, MFC 想不變成標準都有困難... Borland 推的OWL 註定只能消失在歷史的洪流當中.....

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Vic
開墾隊隊長.苦力
等級: 32等級: 32等級: 32等級: 32等級: 32等級: 32等級: 32等級: 32
老得不能再稱小的熊

十週年紀念徽章(五級)   終生苦力熊勳章  

今日心情

 . 積分: 9409
 . 精華: 28
 . 文章: 9949
 . 收花: 79211 支
 . 送花: 10986 支
 . 比例: 0.14
 . 在線: 2902 小時
 . 瀏覽: 187021 頁
 . 註冊: 7982
 . 失蹤: 87
 . 大熊國
#5 : 2005-3-8 07:57 PM     只看本作者 引言回覆

OO是個很好的構想~ 如果世界每種object都被寫出來後....只要會用就可以~ (當然, 有需要時還是要做一些更改)

但OO有時候很麻煩~ 只為了弄個很簡單的功能~ 都要將之object化~ 簡簡單單的東西竟然要寫這麼多code才可以達到~

不過熊是新手啦~ 也許習慣後~ OO弄起來會很easy吧~



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  訪問主頁  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 7978
 . 失蹤: 5330
#6 : 2005-3-8 09:54 PM     只看本作者 引言回覆


引用:
Vic寫到:
OO是個很好的構想~ 如果世界每種object都被寫出來後....只要會用就可以~ (當然, 有需要時還是要做一些更改)

但OO有時候很麻煩~ 只為了弄個很簡單的功能~ 都要將之object化~ 簡簡單單的東西竟然要寫這麼多code才可以達到~

不過熊是新手啦~ 也許習慣後~ OO弄起來會很easy吧~


問題1:
更改? 除非那個Object 有bug... 不然, 不應該是去更改, 而是繼承下來, 然後把某些功能置換成你要的
這也就是維護性問題, 試想, 當結構化程式設計時代, 因為某個function 不合用, 所以把他改掉了, 這時候, 問題來了, 其他使用到該function 的程式, 通通出問題了, 大家一起改... 改到死
so, 使用物件, 必須拋棄以前的觀念, 不應該去更改一個運作正常的物件, 因為更改動作, 將導致其他已經使用該物件的程式造成問題, 而是去繼承他, 然後加上你要的東西, 讓他變成另一個物件

問題2:
我不知道所謂應該粉簡單, 卻弄的粉麻煩是指啥...
不過... OO 的確有overhead, 這是跑不掉的, OO 之所以能夠發展, 憑借的是硬體越跑越快, OO 之所以必要發展, 是因為軟體越來越複雜, 如果不採用OO 的觀念, 舊系統的維護以及新系統的開發都越來越困難.
OO 並不見得讓程式變得簡單, OO 重點在於: 資源可重複使用(也就是一般稱為物件可重用性), 維護可靠性 (前面說的, 物件應該去繼承衍生, 不應該去修改他, 除非有bug), 資料隱密性 (這兒並非說物件內容要隱瞞啥, 而是指, 你不用知道該物件是怎樣寫的, 你只要知道如何使用他)

問題3:
OO 需要的是累積資源, 這跟以前很像, 一個程式熟手, 經常性的把以前的程式碼找出來, 修改一番, 變成新的程式的需求. 只是因為結構化設計的關係, 總是需要想一下原來程式怎樣搞得, 現在得改成啥樣子, 修修補補, 難免產生蟲蟲.
在OO 的觀念下, 則變成, 如果原物件不盡適用, 沒關係, 原物件還是整個copy 過來, 然後繼承下來, 修掉想置換掉的部份, 變成一個新物件. 這樣子, 物件程式庫越來越龐大, 也越來越容易使用, 萬一某日忽然發現, 基礎物件有個小bug, 沒關係, 改掉該bug, 所有用到該物件的程式, 重新編譯後, 同樣的bug 通通改掉了, 一次OK!

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
ROACH
版主
等級: 30等級: 30等級: 30等級: 30等級: 30等級: 30等級: 30等級: 30
減肥中!請勿餵食

十週年紀念徽章(四級)  

 . 積分: 15118
 . 精華: 14
 . 文章: 11766
 . 收花: 140844 支
 . 送花: 6005 支
 . 比例: 0.04
 . 在線: 8869 小時
 . 瀏覽: 85616 頁
 . 註冊: 7973
 . 失蹤: 3
 . 鄉下地方
#7 : 2005-3-8 10:14 PM     只看本作者 引言回覆

這本書在台灣可以買的到
http://www.opentech.com.tw/search/bookinfo.asp?isbn=9572147145



這篇主題??是否要轉到 『讀書會』??? 感覺起來這篇貼出來後~
越來越覺得這篇應該要貼到『讀書會』



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  訪問主頁  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
南無
銀驢友〔高級〕
等級: 14等級: 14等級: 14等級: 14


今日心情

 . 積分: 996
 . 精華: 1
 . 文章: 5126
 . 收花: 6613 支
 . 送花: 5000 支
 . 比例: 0.76
 . 在線: 711 小時
 . 瀏覽: 54263 頁
 . 註冊: 7166
 . 失蹤: 87
#8 : 2005-3-8 10:25 PM     只看本作者 引言回覆

今天看完第二章,對這一章節有一點疑惑

GDT.EIP.IDTR.NMI是用於何處,目的為何


是否能為小弟解惑一下



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Vic
開墾隊隊長.苦力
等級: 32等級: 32等級: 32等級: 32等級: 32等級: 32等級: 32等級: 32
老得不能再稱小的熊

十週年紀念徽章(五級)   終生苦力熊勳章  

今日心情

 . 積分: 9409
 . 精華: 28
 . 文章: 9949
 . 收花: 79211 支
 . 送花: 10986 支
 . 比例: 0.14
 . 在線: 2902 小時
 . 瀏覽: 187021 頁
 . 註冊: 7982
 . 失蹤: 87
 . 大熊國
#9 : 2005-3-8 10:37 PM     只看本作者 引言回覆


引用:
Acute寫到:
問題1:
更改? 除非那個Object 有bug... 不然. 不應該是去更改, 而是繼承下來, 然後把某些功能置換成你要的
這也就是維護性問題, 試想, 當結構化程式設計時代, 因為某個function 不合用, 所以把他改掉了, 這時候, 問題來了, 其他使用到該function 的程式, 通通出問題了, 大家一起改... 改到死
so, 那用物件, 必須拋棄以前的觀念, 不應該去更改一個運作正常的物件, 因為更改動作, 將導致其他已經使用該物件的程式造成問題, 而是去繼承他, 然後加上你要的東西, 讓他變成另一個物件

問題2:
我不知道所謂應該粉簡單, 卻弄的粉麻煩是指啥...
不過... OO 的確有overhead, 這hO跑不掉的, OO 之所以能夠發展, 憑借的是硬體越跑越快, OO 之所以必要發展, 是因為軟體越來越複雜, 如果不採用OO 的觀念, 舊系統的維護以及新系統的開發都越來越困難.
OO 並不見得讓程式變得簡單, OO 重點在於: 資源可重複使用(也就是一般稱為物件可重用性), 維護可靠性 (前面說的, 物件應該去繼承衍生, 不應該去修改他, 除非有bug), 資料隱密性 (這兒並非說物件內容要隱瞞啥, 而是指, 你不用知道該物件是怎樣寫的, 你只要知道如何使用他)

Acute.


這回你說對了~ 大毒王~ OO的確是以繼承來做到符合要求~ 這我說錯了~

而的確...OO 並不見得讓程式變得簡單...這對我們這種只會偷懶的人來說~並不是好事~ 

不過只要有別人寫好又合用的class....那就不同~



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  訪問主頁  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 7978
 . 失蹤: 5330
#10 : 2005-3-8 11:03 PM     只看本作者 引言回覆


引用:
ROACH寫到:
這本書在台灣可以買的到
http://www.opentech.com.tw/search/bookinfo.asp?isbn=9572147145



這篇主題??是否要轉到 『讀書會』??? 感覺起來這篇貼出來後~
越來越覺得這篇應該要貼到『讀書會』


這篇貼這兒應該是正確的
這兒比較算是程式討論區...  ^^"
ED 算軟體, 但是ED 的問題不放軟體求助區
so, 討論程式的書, 也不應該放讀書會才對 ^^"

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 7978
 . 失蹤: 5330
#11 : 2005-3-8 11:16 PM     只看本作者 引言回覆


引用:
南無寫到:
今天看完第二章,對這一章節有一點疑惑

GDT.EIP.IDTR.NMI是用於何處,目的為何


是否能為小弟解惑一下


你怎麼把一堆不相關的縮寫放一起
EIP 應該是程式指位暫存器(Instruction pointer), 本來是IP 後來x86 CPU 由16 bits 轉32 bits, 所有32 bits register 都加上一個E, 變成EIP
NMI 這個是一個硬體名詞, 中文翻譯是: 不可遮罩插斷 (None Mask Interrupt)
GDT 英文全寫是:Global Descriptor Table, 這是386 開始, 因應CPU 出現protect mode 而多的名詞
IDT 英文全寫是:Interrupt Descriptor Table, 也是386 protect Mode 底下的名詞.

這些東西.... 你真想知道, 找組合語言的書來看, 你就知道了, 呵呵, 或者找以前談x86 CPU protect Mode 的書, 也都會詳細解釋.

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 7978
 . 失蹤: 5330
#12 : 2005-3-8 11:24 PM     只看本作者 引言回覆


引用:
Vic寫到:

引用:
Acute寫到:
問題1:
更改? 除非那個Object 有bug... 不然, 不應該是去更改, 而是繼承下來, 然後把某些功能置換成你要的
這也就是維護性問題, 試想, 當結構化程式設計時代, 因為某個function 不合用, 所以把他改掉了, 這時候, 問題來了, 其他使用到該function 的程式, 通通出問題了, 大家一起改... 改到死
so, 使用物件, 必須拋棄以前的觀念, 不應該去更改一個運作正常的物件, 因為更改動作, 將導致其他已經使用該物件的程式造成問題, 而是去繼承他, 然後加上你要的東西, 讓他變成另一個物件

問題2:
我不知道所謂應該粉簡單, 卻弄的粉麻煩是指啥...
不過... OO 的確有overhead, 這是跑不掉的, OO 之所以能夠發展, 憑借的是硬體越跑越快, OO 之所以必要發展, 是因為軟體越來越複雜, 如果不採用OO 的觀念, 舊系統的維護以及新系統的開發都越來越困難.
OO 並不見得讓程式變得簡單, OO 重點在於: 資源可重複使用(也就是一般稱為物件可重用性), 維護可靠性 (前面說的, 物件應該去繼承衍生, 不應該去修改他, 除非有bug), 資料隱密性 (這兒並非說物件內容要隱瞞啥, 而是指, 你不用知道該物件是怎樣寫的, 你只要知道如何使用他)

Acute.


這回你說對了~ 小神童~ OO的確是以繼承來做到符合要求~ 這我說錯了~

而的確...OO 並不見得讓程式變得簡單...這對我們這種只會偷懶的人來說~並不是好事~ 

不過只要有別人寫好又合用的class....那就不同~


老是寫錯字, 而且一錯就是三個字, 該打

OO 的出發點, 物件重複利用本來就是其中一環
當然, 制定一個好的物件的確很辛苦
可是使用該物件時, 卻可以很輕鬆
所以, 把時間花費在建立一個好的物件是值得的
因為將來重複使用時, 就把時間省回來了

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
swimman
驢手小試
等級: 2


 . 積分: 8
 . 文章: 63
 . 收花: 55 支
 . 送花: 5 支
 . 比例: 0.09
 . 在線: 956 小時
 . 瀏覽: 80 頁
 . 註冊: 7172
 . 失蹤: 3257
#13 : 2005-3-12 03:33 AM     只看本作者 引言回覆

現在OO並不是主流了
現在講究的是component base programming了(當然還是用OO)
而且component也流行到了com+而不是舊的com model
最大的差別是com靠的是介面契約,東西會放在REGISTRY
而com+靠的是metadata可以在執行期利用reflection得知元件介面
而且可以允許不同版本的元件並存
最重要的是微軟全力推了十年的com現在也被他們自己踢進了垃圾桶
現在微軟全力再推.net架構
回歸到主題寫程式是一種專業,不會有瞬間暴增一甲子功力的事



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記

   

快速回覆
表情符號

更多 Smilies

字型大小 : |||      [完成後可按 Ctrl+Enter 發佈]        

溫馨提示:本區開放遊客瀏覽。
選項:
關閉 URL 識別    關閉 表情符號    關閉 Discuz! 代碼    使用個人簽名    接收新回覆信件通知
發表時自動複製內容   [立即複製] (IE only)


 



所在時區為 GMT+8, 現在時間是 2024-3-29 03:23 AM
清除 Cookies - 連絡我們 - TWed2k © 2001-2046 - 純文字版 - 說明
Discuz! 0.1 | Processed in 0.052012 second(s), 6 queries , Qzip disabled