軟體開發技術名詞
“Win32程式設計”
很不幸,我從開始學習程式設計到理解這個名詞中間隔了很長的時間(上個世紀的學習環境可見一斑)。很長時間裡我都不明白32是指什麼,我用過Dos,Win31,win95,win97…但好像沒用過名為Win32的作業系統啊?很久以後我才知道,32在這裡並不是指作業系統的版本號,而是指32位。微軟作業系統在win31及其以前都是DOS系統,windows只是在dos下執行的一個大程式而已。在其後win95則稍有改變,windows除了DOS核心以外也真正成為了作業系統的一部分,提供著各類作業系統提供的服務。應該說,在win95之後的windows(新近的64位win系統以前)都可以稱之為win32系統平臺(95/98實際上是16與32位混合)。所以在這樣的平臺上,直接或間接使用系統提供的API程式設計,就稱之為Win32程式設計。對Visual Studio而言,Win32程式設計一般指SDK、MFC、ATL這幾類開發方法,其中ATL在國內應用不是很廣泛,一般應用於以COM元件為架構的中大型軟體產品。
“SDK” :Software Development Kit,常譯為軟體開發(工具)包
在Win32程式設計領域一般指與MFC這類框架程式設計相區別的,直接呼叫Windows提供的API的開發方式,與字面原意有一些區別。另外一個經常見到的說法就是某軟體(硬體)帶有自己的一套SDK,這裡其實一般是指一套API庫函式或者類庫,供上一層的開發者呼叫。又譬如常說的DX的SDK,其實是微軟開發的一套COM元件,供上層開發者使用。總之,供程式設計師使用的比較完備的程式碼庫,就可以稱之為SDK;
“MFC”: Microsoft Fundation classes 微軟基礎類庫
大家都知道,使用SDK程式設計方式往往有很多每次都重複的固定不變的一些程式碼,為了提高程式設計的效率,減少上千個API帶給開發人員巨大的精神壓力,微軟開發出了這麼一個類庫,注意,這個類庫與作業系統本身無任何關係,它只是對API進行了一個面向物件的封裝,當然,還給出了一系列程式設計的框架。使用SDK的方法,使用Visual Studio,通過呼叫Windows API,MFC你也可以做得出來。MFC把一些固定不變的程式碼已經寫好了,只在編譯時候鏈上,所以我們的程式碼裡看不到WinMain(),而事實上整個程式的執行,和SDK的方式無任何區別,初學者請記住這一點。另,補充一點個人感想,MFC的初衷,帶給開發人員更多的便利,我覺得並不太成功。學習MFC所費的力氣和最終的所得,並不太成正比。
“API”:Application Programming Interface,應用程式介面
這個詞的出現頻率很高,從某種意義上來說,也可以看作是SDK的一個子集。這也是做給程式設計師的程式,不過一般指用匯出函式的方式提供服務的函式庫,不包括類庫和元件。
“GDI”:Graphic Device Interface,圖形裝置介面
這個是Win32程式下最常用的顯示方式,與DirectX、OpenGL處於同一級。在DOS要顯示一些東東可不是容易的事,最簡單的是呼叫一些C的圖形庫函式來實現顯示,不過一般也就是些畫線,填色,輸出幾個文字,效果很弱(所以DOS程式介面一般都不怎麼樣,且實現起來不是一般的複雜),要複雜一點的動畫/圖片顯示什麼的,經常要用到的就是硬體中斷,呼叫一些顯示卡自身的子程式(固化在顯示卡內的)來做。因為每一個顯示卡都不同,所以DOS的遊戲相容常常由於顯示卡的差異而很糟糕。到Windows下大家就幸福多了,Windows將硬體這一層遮蔽起來,用一個表格(Device Context)來代表一個顯示,我們要做的就是在這個表格上填好相關引數,然後畫上我們想畫的東東,然後作業系統會依照這個表格(DC),把相應的顯示內容(一般是一塊顯示記憶體)傳送到指定顯示卡的指定的視訊記憶體,再由顯示卡傳給顯示屏。我們不再需要與不同的顯示卡打交通,這是一個十分偉大的勝利!GDI中最常用的是雙快取技術,就是說你可以在記憶體中建立(也就是複製)一個DC,只不過在這個DC中顯示的不再被傳送到顯示器上。有什麼用呢?因為它的各引數是與當前螢幕DC一致的(COPY嘛 ,當然是這個結果),所以它的顯示內容可以完整無失真地傳送到螢幕DC上。我們通常在記憶體DC上畫圖,譬如畫一圓,再畫一條直線,畫完後一次性地傳送到螢幕DC上,這樣對使用者來說螢幕只重新整理了一次,可以解決你畫一點內容螢幕即重新整理一次導致的閃爍問題。當然,雙緩衝甚至多緩衝還有很多別的用處,那就要靠自己揣摩了。
“DirectX”
通常簡稱為DX(讀音:低叉)這是個很吸引人眼球的名詞,讀起來就很上口:)。Windows為我們作了許多遮蔽底層硬體的工作,其中DX是最知名的技術之一。作業系統要與各類硬體打交道,特別是多媒體相關的,譬如顯示卡、音效卡、手柄輸入、多媒體流的網路傳輸等等,這些事情如果都自己來弄的話,那就太要命了(這些一般都涉及系統底層,自己也很難做出來)。而DX則正是這麼一套作業系統提供的隔離多媒體硬體與程式設計師的間質,DX自身一般並不實現處理的能力,它是一個標準,要求硬體來滿足,好比DX提供一個函式名,硬體來實現函式內容一樣。通過它我們可以非常簡單而快速地呼叫硬體提供的各類服務。它主要包括DirectDraw(通過直接訪問顯示硬體來提供快速的圖象處理能力),DirectSound(提供了軟硬體的低延遲聲音混頻和回放,以及直接訪問音訊裝置的能力),DirectPlay (它明確的提供了通用環境連線能力來簡化你應用程式之間的通訊服務),Direct3D(DirectDraw的3D版),DirectInput(簡化你的應用程式訪問滑鼠、鍵盤和操縱桿裝置的能力),DX5.0之後又增加了一些(如DirectShow),不再詳述。DX一個重要的特點就是你可以通過它直接訪問硬體而無需知道硬體的具體細節。譬如DirectDraw,就能夠越過記憶體而直接訪問視訊記憶體,這樣的速度將比GDI快很多,不在一個數量級上。補充一點:DX是以元件的方式提供的,而不是通常的匯出API的形式。DX SDK的最新版本是9.0
“COM”:component object model,元件物件模型,一般簡稱元件
這是微軟為了解決程式碼重用的一個重要機制。重用程式碼的最簡單辦法是原始碼重用,把寫好的函式和類加到自己當前的程式碼中,編譯即可。簡單是簡單,敝病卻顯然的多。另一個常用的方法是單獨做成模組,以DLL的形式分發,DLL匯出函式或者類,客戶程式用動態/靜態連結的方法將其載入,這顯然比前一種原始碼的方法好一些,難度也不大,最為常用。但DLL也有一些不足,最根本的,它不是二進位制相容,DLL版本升級一次就需要與客戶程式程式碼重連結一次,有些時候這幾乎是不可能的任務。為了更好地讓程式設計像“搭積木”一樣簡單,讓模組可以完美地配合,完美地替換,COM產生了。COM不是類庫,不是程式碼,不是作業系統的服務,而是一套程式設計模型,理論上來說,它與語言無關,與作業系統無關,unix下同樣可以做COM。COM是一種程式結構模型標準,你做的DLL或EXE在結構上滿足這麼一個標準,那這個DLL或EXE就是一個元件,它將在該平臺上成為二進位制相容。COM主要利用了登錄檔來登記本模組的資訊。客戶程式呼叫時首先查登錄檔,找到所需元件的位置(這實現了位置透明),然後就用Loadlibrary把它載入進來,這和普通呼叫沒有本質區別,區別在於由於元件特殊的實現方法使得整個過程中使用者程式都不知道元件的位置,元件的類的例項化過程,如何銷燬,不能直接訪問元件的任何實現細節,使用者只與元件的幾個public介面打交道。這將實現真正的模組之間的獨立。對使用者程式而言,對於目標元件的認識,除了介面,一無所知。在介面不變的情況下,元件可任 意替換而客戶程式不作任何改動,無需編譯,僅這一點,在中大型程式的模組整合的過程中就將節約相當多的時間。
“STL”:Standard Template Library,標準模板庫
這是最早由Alexander Stepanov和Meng Lee(蠻像中國人的名字)完成,於1994年提交給ANSI/ISO 標準C++委員會並通過而成為標準C++的一部分。望文生義即可知這是一個程式碼庫標準,不是語法標準。簡單地說,STL是以C++中的模板語法為基礎建立起來的一套包含基礎資料結構和演算法的程式碼庫。STL的特點是實現了“型別引數化”,即STL的程式碼中可處理任意自定義型別的物件,如果不使用模板技術的話,這是一件相當困難的事。也因為這個原因,在最新的java及C#語法中均加入了對模板語法的支援,可見其重要性。另外一個有關STL重要的話題是GP(Generic Programming),泛型。這是與面向物件相併列的另外的一個程式設計模型,它以模板為基礎,弱化了實體型別的差異,簡化了程式設計時問題抽象的模型,提供了更好的封裝性和彈性,對於繁雜的面向物件程式設計毫無疑問是一種解脫,至少是精神上的。GP並不是用來取代面向物件的,而是作為一個有益的補充體,是面向物件很好的合作伙伴。GP是最近幾年軟體架構的一個研究熱點,但國內真正的應用似乎並不多見,這項技術本身還基本處於研究前沿。<>一書對C++中的GP應用有很好的詮釋,而這本書對腦細胞的殺傷力之大,也是其它C++書藉望塵莫及的。想知道C++的程式碼技巧
可以做到怎樣的出神入化嗎?不妨看看這本書。
“ATL”:Active Template Library,活動模板庫
這在VC程式設計下應該算是比較高階的話題了,它集COM和模板技術於一身,帶來了極方便的元件編寫方法和極高的學習門檻。可以說,進入ATL領域就算是進入了中級以上的程式設計領域。ATL是為元件而生,它的目的是為了讓程式設計師更方便地編寫元件(純用C++寫一個最簡單的元件實現一個“Hello World”對初學者來說都是要命的),同時它使用模板技術來類似於MFC一樣建立了一個開發COM的框架程式碼庫(模板庫),使用該框架及模板庫可以相對方便地進行元件開發。ATL中的一個特點就是你自己的類將成為ATL程式碼庫中某些類的父類,這是一件很有趣的事(這也是模板技術的一個特點)。
“HANDLE”: 控制代碼
這是一箇中文翻譯很古怪的字,對初學者來說是百思不得其解的東東。這其實等價於void*(順便提一下,初學者往往對VC程式碼中各種古怪的符號、型別標記/巨集等百思不得其解,其實它們大多來自基本型別的#define或者typedef,請將游標移到這些符號上(譬如HANDLE),然後按下F12,編譯器自會把你帶到它的宣告處,反覆使用幾次,你終會見到它的原貌,然後長吁一口氣:原來不過如此而已。沒用過的初學者請牢記:F12)。很多初學者總想知道一個HANDLE代表一個什麼物件,我的建議是不要去理解為某物件,而就是理解為訪問某一個物件的入口,事實上HANDLE大多數時候是一個整數索引(標誌該物件在作業系統的某表中的位置,就好像一個數組的下標一樣),Windows系統核心中主要是幾張大表,這樣一個整數索引就是標記目標在這個表中的位置,供作業系統訪問時查詢用。偶而它的確是指向某物件的指標,有時它還攜帶一些額外輔助資訊。總之,我們不要去直接訪問它,把訪問HANDLE的任務交給作業系統好了,除非你還嫌寫程式不累:)。
“DLL”: Dynamic Link Library 動態連結庫
DLL的一個特點就是可以動態載入(顧名思義),即在主程式(我更喜歡稱為客戶程式)需要該模組時才由作業系統載入到記憶體。畢竟一個大型應用程式我們經常使用到的功能並不多,這樣一些不常用的功能模組(DLL)在程式執行時一般將不被載入,可極大節省記憶體開銷。DLL同時也是目前最常用的分發模組的方法,便於彼此協作。程式中對DLL的呼叫主要有兩種方法:1 針對使用DEF檔案匯出函式的DLL,使用API函式LoadLibrary(“DLLModuleName” )載入,然後使用GetProcAddress()得到函式指標,進而呼叫 2 直接將類、函式等匯出,客戶程式使用同一份標頭檔案宣告,加入對應的lib連結庫,即可在客戶程式中直接使用DLL中的類或函式,無需LoadLibrary。
“Process”: 程序
程序是一個動態的概念,包括從程序的建立申請,PCB(Process Control Block程序控制塊,一般作業系統實現為一個表格(struct))的建立,地址空間的記憶體分配,模組程式碼載入並執行,執行完以後進行撤銷,整個過程被稱為”程序”。在Win32下,一個程序有4G的邏輯空間。但我們也常把它作為靜態概念來使用,在Win32下,一個EXE的執行就是一個程序(如果它內部又開了新程序,另當別論)。
“Thread”: 執行緒
為了更有效的提高CPU的利用率,更好地實現多工併發,微軟將程序進行進一步分割,實現了CPU任務排程的新對像:執行緒。一個程序擁有至少一個執行緒。我們在實現多工併發的時候通常是建立一個新執行緒(建立執行緒的系統開銷要小於程序),執行緒以我們自己的一個函式作為入口,函式執行完畢自動撤銷(當然你也可以在執行過程中強制結束該執行緒)。順便提一下,在UNIX下並沒有執行緒這個概念,想來是因為UNIX主要是以多程序的併發服務為主(所以它更適合於做伺服器),系統執行時通常已經有了太多的程序,所以沒有必要再對程序進行細化,因為這樣做甚至會降低系統效率(CPU排程不過來),當然,這是我個人的猜想:)
“C語言”
到目前為止,C語言應該是傳播最為廣泛的語言,特別在UNIX的世界裡依然扮演著主角的位置,在其餘如硬體開發,嵌入式系統(如手機)皆有十分突出的表現,即便在win32平臺下SDK的開發中也有一席之地。更主要的是它是大多數國內(國外我不敢說)程式設計師的啟蒙語言,通過它許多人才領會了程式的思維。C最大的特點就是快,除了彙編以外效率可以達到最高,而它的靈活性,對硬體的直訪性也完全符合程式設計師自由的天性。如果說學習別的技術尚有猶豫和徘徊,那麼學C只有一句話:相信我,沒錯的!也有許多人主張可以直接學習面嚮物件語言,我不太同意。面嚮物件語言對機器模型的抽象十分容易讓程式設計師迷糊,心中難以建立準確的程式執行時的模型。畢竟我們是程式設計師,不是使用者,我們不能把所有的問題都想當然地交給編譯器和作業系統去解決,它們也解決不了。至少學習一門面向過程的語言,才能知其所以然。
C++
這是貝爾實驗室的又一傑作,同時,也傷透了全球太多程式設計師的心,腦細胞殺傷力十分之大。C++比大多數初學者想像的都要複雜得多,它基本包括:一個類化了的C語言,模板,標準模板庫.很多初學者掌握的C++僅僅只是一個類化了的C語言的一個子集(不相信的話,你不妨看一看<>中的C++程式碼,看看能理解多少)。更麻煩的是使用C++不得不談到面向物件的程式設計風格,這同樣比初學者想像的難很多,要有打持久戰的準備。而最讓我這類C++愛好者憂心的還是它目前在Win平臺中的前景,在.net平臺上很難找出不用C#而使用C++寫新程式碼的理由:( 。而它的複雜性和目前許多諸如java/C#及一些動態語言(python/ruby)比起來,開發效率顯然的低,大有退出上層應用程式開發的趨勢。這麼一個包含了最多正規化的近乎完美的語言,我實在不想放棄。我唯有祈禱在未來C++的路可以走得更遠更好一些。
原始碼版本控制
這是軟體開發中一個十分重要的工程手段,幾乎是必須的一個Process(過程)。很多作坊式的開發團隊在採用軟體工程的一些方法的時候,第一個要進行改進或增加的,往往就是這個過程。對初學者學習而言,建議在開始進行實踐小專案的階段即進行原始碼版本控制,因為這在以後的工作中,是一定會用到的。
原始碼版本控制的基本原理如下:
在伺服器端建立該專案的資料庫,並儲存你選定的專案原始檔的第一個版本。客戶端任一使用者要獲得某原始檔的修改權利,需進行check out操作。之後客戶端一般每完成一個無編譯錯誤的版本想儲存的時候,進行check in操作,將當前版本儲存在伺服器端上併成為最新版本(注意,不是覆蓋以前的喲)。任一客戶端可以方便地得到伺服器上的檔案的任意版本(如果有許可權的話)。一般還實現了一個重要的功能是版本比較,任一客戶端可以利用版本控制工具對某檔案的不同版本進行版本比較,它會標記出不同版本的同名檔案的不同點,可以輕易地看出版本內容的演化,這一招很常用。 下面介紹一下我接觸過的三種版本控制工具(也是國內用得比較多的):
VSS: Visual Sourcesafe
這是微軟Visual Studio自帶的原始碼版本控制工具,它最大的特點就是易安裝(與Visual Studio整合在一起,裝VC/VB的時候就順便搞定,不用別外費工夫),使用簡單(伺服器端設定相對容易,一般個人稍加摸索就可以輕鬆搞定,客戶端更是隻管check in/out),基本功能完善,版本比較很直觀(我喜歡)。它的特點是某人check out了某版本以後,別人將無法對此版本check out,也就是說同一時間只有一個可以修改某一個檔案,這樣就避免了不同的人對同一檔案的修改造成彼此衝突(注:可通過設定伺服器端實現多人check out,但幾乎不會這樣做,因為那樣就失去了VSS的一個最重要的功能)。另,VSS可集成於VS環境,但根據我的經驗,直接在VC裡對版本的check操作,常常不生效,所以最好還是到VSS程式裡去進行check操作。補充:單機上也可以使用VSS,這樣的好處是在對當前某些檔案進行了誤操作或大規模地誤修改之後,可以恢復到最近的無錯誤的版本,最大程度地挽回損失。VSS實際應用較普遍,如果你是走Visual Studio路線的話,一定要用一下。
CVS: Concurrent Versions System
這個也是一個大名鼎鼎的開源的版本控制工具,主要活躍在UNIX世界。CVS我使用不多,一般而言好像功能比較偏向於命令列方式(UNIX下開發很多人也都使用著命令列方式)。當然,Windows下面也實現了幾個版本的CVS,也可以集成於VS,好像還有一個可以掛接在IE上的,我沒試過。著名的開源專案管理網站sf.net也是用的CVS,如果你要和全世界的程式設計師一起協作開發,CVS是必須要安裝的。在JAVA的世界裡,也是以CVS為主。
Rational Clearcase
這個工具就比較上檔次了,Rational公司(現在是IBM)的出品,價格昂貴。我最初參加工作的時候用過一小段時間,簡單談一下。這個工具的特點是複雜,安裝及設定就十分複雜,我的印像中客戶端甚至不得不加入到NT域裡面去,導致我在本機的許可權都不夠,安裝新程式都很麻煩,很鬱悶(不知道是不是我們公司的相關人員安裝設定錯了,想來應該是這樣,但其複雜性可見一斑)。對使用而言,它有一個功能挺有用的,就是它能夠根據你每次check的版本號,自動生成版本樹(一個樹狀圖表),你可以清晰地看到版本的演化過程。所以嚴格地說,像CVS/Clearcase這樣的才真正稱得上“版本”控制,VSS還太勉強。Clearcase的功能十分強大,我不詳述了(我還不想出書),較適於大型軟體公司實施軟體配置管理時採用。雖然它的名氣十分之響亮,但我不知道國內有多少公司在真正使用正版的Clearcase這樣的工具,想來應該是十分之少。
OpenGL
OpenGL至今頗有一點英雄落寞的味道,這一套標準是實現得如此之好,以至於曾經一度成為遊戲介面華麗的標準。它的低落也是一個必然,畢竟在微軟的強力打壓下鮮有不挫敗的。但它曾經能夠給微軟帶來如此的壓力,至今也依然在工業界被廣泛使用,大多數遊戲/顯示卡依然保留著對它的支援(CS裡我喜歡的還是OpenGL)。而它的效能在某些方面與D3D比較,依然佔著上風。不幸的是DirectX在不停地向前發展,而它,幾乎止步不前了,前景並不光明。OpenGL目前在工業領域應用較為廣泛,它的優秀的向量圖的操作效能,華麗的色彩,在專業的圖形影象處理領域表現突出。遊戲中使用相對以前而言則是越來越少。新近聽說微軟的最新作業系統Vista對OpenGL進行了極大的打壓,不但效能上折扣,支援的版本也只到1.4(最新版本好像是2.0),不知道最後如何收場,拭目以待。
DirectDraw & D3D
大凡像樣的2維Windows遊戲,幾乎都是採用此技術來實現顯示的。DirectDraw有兩種模式:全屏和視窗。其中全屏應用更多一些。在全屏下,DirectDraw有一個十分著名的“換頁”技術,即在兩個顯示頁面之間用“交換”來實現顯示重新整理,這個速度十分地快,只是一個視訊記憶體內一個指標的交換,比你用BitBlt複製一屏的畫素快太多太多,遊戲的高效的動畫效果大多源於此技術。
DirectDraw主要用於娛樂領域和一些實時顯示要求較高的場合,如醫療影象。D3D是目前大多三維遊戲的標準採用,我沒鑽研過,不敢多言。它的效果嘛,玩玩遊戲就知道了:)
UML:Unified Modeling Language,多譯為統一建模語言
這個語言是一種圖形語言,主要是作為設計時建模的一種標準的圖形模型,便於程式設計師與程式設計師、程式設計師與客戶、設計員與程式碼員之間的溝通,同時它也幫助設計人員將頭腦中的基於程式程式碼的對程式功能的理解形成文件,便於理清頭緒,進行下一步編碼的工作。換言之,設計過程的產品,可以表現為一些文字文件,或者一些框架程式碼,或者一些虛擬碼,但比較標準通用的,是表現為一堆UML圖。UML包括動態圖和靜態圖兩大類,其中靜態圖中的類圖最為常用。很多人初學時不知道該怎麼做設計,寫小軟體時常常沒有設計過程,其實很簡單,把軟體的類圖畫出來就好了。學做設計時未必要找一個像Together或者Rational Rose一樣的巨無霸。用一些簡單的可以做UML圖的工具就好,專門用來畫UML圖的小工具很多,網上容易找。補充一點:畫UML圖不要面面俱到,不要什麼都畫,突出重點方便理解就好,甚至使用不規範的記號也不要緊(當UML的功能是草稿的時候)。
RTTI: Runtime Type Information 執行時型別資訊
在程式中,當我們得到某一個物件的例項或者指標時,大多數時候並不能直接肯定它的型別(都是繼承以及型別轉換惹的禍),這個時候,依靠VC4.0或更高版本的編譯器提供的RTTI支援,呼叫庫函式typeid()即可在執行時獲取這個物件的“型別資訊”,在一些動態處理中“型別資訊”很重要,獲取了型別資訊以後,你就可以有十分把握地呼叫該型別的相關操作,或者型別轉換,或動態生成。因其重要性,在JAVA和.net庫中藉助單根繼承和“虛擬機器”對此有了更優雅的做法,每一個自object繼承的類天然就有了表述自己型別資訊的能力(繼承的好處),並且容易擴充套件,現在你需要型別資訊的時候,大可直接ask那個物件:tell me, what type are you?它就會告訴你答案。
debug & release 除錯 & 發行
大家都知道,debug是除錯版,release是發行版,區別在於debug版生成的程式中包含大量供除錯用的場景程式碼(不是真正執行需要的),而release一般去掉了這些資訊,並進行了某些程式碼優化,所以release版的程式會比debug版的程式小很多,執行速度也快一些。同時,debug版為了便於除錯,往往會對除錯使用的診斷程式碼加上DEBUG一類的巨集,使得在release下不對這些程式碼進行編譯。正由於兩種版本編譯使用的原始碼的差異(以及release糟糕的優化),常常使得兩種版本執行時產生截然不同的效果,一個正常一個崩潰是大多數人都遇到過的。導致問題的可能性很多,注意事項詳見各論壇的諸多精華貼。另,同一個程式如果DLL之間的連結使用了不同版本(譬如EXE是release版,dll是debug版),有時會無法正常執行,所以我一般的做法是每一個DLL針對不同版本使用兩個DEF檔案,編譯生成不同名的兩個檔案(debug版檔名後加d),呼叫時各個版本針對自己的版本呼叫,這在一定程度上可避免混亂。另,release也是可除錯的,在工程設定裡把除錯資訊開啟即可。
XP:eXtreme Programming 極限程式設計
這是近幾年才時興起來的開發模型,國內大致是01/02年開始有所宣傳。
它主要是針對中小型開發團隊在開發時間要求緊、需求不穩定的中小專案(大多數軟體專案都是這個情況)時使用。它打破了傳統軟體工程的框架,非常新巧。譬如整個開發過程中文件很少,大量使用“卡片 (如CRC卡片)”來描述開發計劃和內容;沒有真正意義上的軟體功能規格說明書,取而代之的是一系列可測試的用例;沒有獨立的設計和測試階段,它們總是在迭代中增量反覆進行;設計:儘可能小和簡單;一般沒有程式碼複審(code review),大家共同擁有程式碼。而它的最顯著的一個外在特徵是它常使用“成對開發”,即一臺機器前坐兩個開發人員,共同開發(一個看,一個寫),這乍聽起來真是蠻有趣的:),它的基本出發點是認為成對開發的效率在一定條件下要高於兩個人獨立開發的和。不要覺得天方夜譚,在很多專案中,這種做法的有效性已經被證實。
XP的特點可以用“快、小、靈”來概括,它和傳統瀑布模型(自頂向下)的區別在於它使用迭代增量(設計->程式碼->測試->設計->程式碼…)的方式。想法很簡單:沒有什麼目標是可以一開始就容易確定的。用爬山來做一下比喻的話,傳統的是在山下研究地圖,選好一條路線,然後沿著此路前進,XP則是走一走,停一停,看一看,對下一步的方向作出新的選擇,在很多時候,這樣做會讓你選擇到更好的捷徑。
ICONIX:
這個字相信很多人都沒見過,我也不知道是什麼字拼起來的,作為開拓眼界,我還是提一下吧。這是一種界於XP和RUP(Rational Unified Process)之間的開發模型,換言之,它比XP“大”,比“RUP”要小。它採用了UML的一個子集,特點是用例驅動,保持良好的進度跟蹤能力。它的目標是用最短的時間來把用例變成程式碼。具體來說,這種開發模型相對精簡的XP而言,更加強呼叫例的建立、分析和程式碼化,用例是其中心地位。
RUP:Rational Unified Process
前面已經提到了,相信你已經感覺出它是一個豐富的軟體開發模型。這是由IBM提出來的軟體工程模型,它使用完整的UML圖,對開發的各階段(需求、設計、程式碼、測試、維護)均有十分完善而複雜的標準,就不詳述了。RUP本質上是迭代式開發,在每一次迭代中均完成以下四個階段:初始階段(inception)、詳述階段(elaboration)、構建階段(construction)、轉換階段(transition)。
CMM:Capability Maturity Model 軟體成熟度模型
這是卡內基*梅隆大學軟體工程研究所(我的專業正是軟體工程,所以這也成為我心目中的聖地)的一大力作,一度曾形成了席捲全球軟體開發的CMM浪潮。CMM分為五級,大多數軟體企業都處於第一級,而得到第五級認證的全球也沒有多少,國內去除掉掛羊頭賣狗肉的,也是寥若星辰(嗯,比星辰是寥多了)。所以CMM實施一般是從第二級開始,能做到第三級的都是頗有實力的軟體公司了。CMM是以Process(過程)為中心的模型,從二級始每一級都有幾個Key Process(關鍵過程),每一個KP又分為若干Key Active(關鍵活動)。CMM的實施一般不能越級實施,並且每一級的實施通常都要一年以上,所以要達到較高等級是一級很困難的事。另,CMM不僅可用於較大規模公司,同樣也可實施於小公司,小專案組(這是很多人所不知道的)。實施視具體情況等級之間可交叉,譬如實施時採用二級的某些KP再加上三級甚至四級的KP,但你只有實施了所有二級的KP,你才能也只能通過二級認證,即便你採用了某些四級的KP。CMM最新發展成果是CMMI(Integration),這主要是新考慮了軟體與非純軟體因素的關係(譬如系統),以及團隊之間的協作問題。CMM在國內的發展似乎有點走向ISO同樣的道路,這實在不是一個好訊息。
Callback Function: 回撥函式
在侯sir的<<深入淺出>>中一開始就提出了這個概念,大概的提法是說回撥函式是作業系統呼叫而你永遠不要去呼叫的函式。這個提法讓初學者有點望而生畏,以為是一種多麼高深而難以領會的系統底層的核心技術。其實不然,這個技術本質很簡單,而且很常用。它實質就是函式指標的基本運用(如果不知道什麼是函式指標的話,翻翻書)。在一個模組中,有時想讓一部分功能由其它模組實現,譬如說一個做顯示的模組,它只想實現顯示的資源配備,畫面的重新整理,縮放等控制功能,而把畫具體實體(譬如圓、多邊形,都可以有很多種不同效率的實現方法)的程式碼由別的模組來實現,怎麼辦呢?用函式指標。在自己的類中放一個畫圓的函式指標,使用時由外部為這個函式指標賦值(其實就是指向了一個外部的函式),在自己的程式碼中直接呼叫這個函式指標來畫就可以了(本模組完全不知道外部模組是怎麼畫圓的)。那個外部的函式在這裡就是回撥函式!
在很多系統API中就使用了這種函式回撥的方法,讓我們開發的程式碼實現可以嵌入到API的程式碼實現當中,其實我們就是傳了一個函式地址給它而已。換句話說,這些API搭好了某些執行的程式碼框架,我們來為它具體實現。
XML: Extensible Markup Language 可擴充標記語言
也許你還在為選擇.net和j2ee而徘徊不前,如果是這樣的話,不妨先著手學一下它們所共通的一個基礎:XML。有了HTML為什麼我們還要XML?很簡單,HTML重在表現文字/圖片以及一些多媒體內容,它很難表達資料,因為它的標記是固定的,而資料型別千千萬,根本無法描述。.net和j2ee都要解決一個資訊傳輸格式標準化的難題,這個格式要能承載文字/資料,最好還能描述程式介面,同時又應該像HTML一樣簡單,具有通用性,能夠在HTTP下很好的運作。在這種要求下,XML產生了。它的特點正如其名,和HTTP一樣,它也是一種標記語言,但是它的標記不是固定的,是可自定義(也就可無限擴充套件)的,這些自定義標記能夠很好的描述資料型別以及對應的資料內容(乍看起來很像資料庫表的定義)。除此以外,XML還可以描述程式介面,所以XML可以方便地與網路程式構件(COM、EJB等)直接互動。由於它也是一種ASCII文字流,所以與當前的HTTP相容,在當前的internet上暢通無阻(這很重要)。有了以上功能,XML就名副其實地成為了新一代網際網路技術的標準資訊載體,在.net和j2ee的網路架構中,各種“構件”的資訊互動都交給了XML,可謂任重而道遠。
XML我自己沒怎麼寫過,單就學習上的經驗而言,感覺語法上比HTML更瑣碎一些,小細節更多,沒那麼容易速成:) 好在根本同源,有HTML基礎甚至WEB開發基礎的,學起來也很輕鬆。
Java2:
這是近幾年最吸引大眾焦點的語言,在Web開發,網路平臺,移動開發的世界裡發光發熱。你可以不用java,但你不可以不瞭解java,畢竟這是一個極大且豐富的軟體開發領域。有些沒使用過java的VS陣營裡的人可能還不明白java2裡的那個2是什麼意思,容我先解釋一下。Java最初正式推出1.0時,並沒有受到如此多的好評,受到頗多責難,於是它不斷地推出新版本來完善自己,其中變化顯著的一個版本是1.2(我沒記錯吧),Java的每一個新版本除了語法上的更新,還有一明顯的標誌,那就是JDK(Java Development Kit,就是Java自帶的一套SDK)的更新,版本1.2以後的java為了在宣傳上與以前的java相區別,便被稱為java2。目前用得比較多的jdk是1.3/1.4 ,最新的JDK是1.5(代號tiger)。java開發的IDE國內主要以JBuilder為主,另外就是在開源領域如雷貫耳的Eclipse,而sun也力推自己的開源java IDE:Netbeans(從sun的網站上可下載,免費)。Java執行是虛擬機器機制,相當於在作業系統上增加了一個軟作業系統,原始碼被編譯成一種位元組中間碼,由虛擬機器解釋執行,只要有對應的虛擬機器,java程式就可以在該作業系統上執行,這就是java號稱的一次編譯,到處執行的由來。而附帶而來的不可避免的效能問題也讓Java難以成為桌面程式開發的主流。補充一下:對初學者學習而言最好的Java IDE我推薦使用JCreator,這是一個C++寫成的IDE,幾MB的大小,比Eclipse快十倍以上的啟動速度,對初學者帶來極大的便利。
J2EE:
Java實際上又被分為3類:J2EE/J2SE/J2ME,不同類分別對應不同的JDK,J2EE針對企業平臺開發,J2SE是標準版,J2ME針對移動平臺開發。J2EE現在實在是熱得燙手,我前不久翻了一下程式設計師早期的雜誌,發現在第一期創刊號裡(2001.1)已經有了j2EE方面的討論,現在已經是2004.6了,你對它的認知又多了多少?J2EE不是一種單純的技術,而是一種體系架構以及組成該架構的諸多標準。企業平臺開發和桌面/簡單Web資料庫開發有很大的不同,它的程式規模往往很大(不是一個或者幾個EXE可以搞定的),用到的往往是海量的資料庫和海量的通訊,並且常常是不可中斷的,這些特殊性都使得企業平臺開發更多地去關注架構的問題。而我們寫一個熟悉的java客戶端程式,或者訊息處理中介軟體,又或者資料庫處理程式,都只是這樣一個架構裡的一小部分。J2EE是很寵大的,所以請不要寫了幾個EJB(這是java世界裡的構件,概念上大概是類似於COM)的例子程式就感覺自己精通j2EE。
J2EE中傳遞訊息時往往引入了一個被稱作訊息管理器的中介軟體,在伺服器端使用EJB的容器來管理和呼叫EJB。在J2EE中一個重要的概念是Transaction(事務)處理,事務的概念最早廣泛應用於資料庫技術。這實際上是一個封裝了很多操作的單元,它的作用是中間任何一個操作失敗,可以自動依次整體撤銷,所以一個transaction就是操作成功/失敗的最小單元,不存在一個transaction只成功了部分操作的情況。
在企業服務平臺開發中比較知名的有一個叫BEA公司(這是一家不錯的公司,應該知道它的名字),它的產品是Weblogic。
.net
.net是微軟為下一個十年準備的技術,你呢?.net也是一種平臺技術,而不是單一技術。它主要分為.net執行時平臺(對應java的虛擬機器)和.net類庫(對應java的jdk)。目前只有Windows2003是天然集成了.net執行時平臺的作業系統,所以如是你寫的.net程式想要在別的作業系統上執行,該作業系統必須先安裝.net平臺,這是一件蠻煩人的事,也是為什麼到目前為止,還沒有太多的人改用.net來寫程式(儘管可極大提高開發效率)。希望Longhorn的出現可以扭轉這一現狀。那我們就終於可以和MFC這樣過時的框架類庫說再見了,一大快事。
.net採用了很多最新的技術和思想,對走VS路線的人來說(特別是有COM概念的),學起來相對輕鬆且很過癮,前人推薦的“.net框架程式設計“和”.net本質論“都是很好的書。當然,看它們之前你最好基本掌握一門.net語言,譬如C#,掌握語言對我們來說是最easy的。
很不幸,我從開始學習程式設計到理解這個名詞中間隔了很長的時間(上個世紀的學習環境可見一斑)。很長時間裡我都不明白32是指什麼,我用過Dos,Win31,win95,win97…但好像沒用過名為Win32的作業系統啊?很久以後我才知道,32在這裡並不是指作業系統的版本號,而是指32位。微軟作業系統在win31及其以前都是DOS系統,windows只是在dos下執行的一個大程式而已。在其後win95則稍有改變,windows除了DOS核心以外也真正成為了作業系統的一部分,提供著各類作業系統提供的服務。應該說,在win95之後的windows(新近的64位win系統以前)都可以稱之為win32系統平臺(95/98實際上是16與32位混合)。所以在這樣的平臺上,直接或間接使用系統提供的API程式設計,就稱之為Win32程式設計。對Visual Studio而言,Win32程式設計一般指SDK、MFC、ATL這幾類開發方法,其中ATL在國內應用不是很廣泛,一般應用於以COM元件為架構的中大型軟體產品。
“SDK” :Software Development Kit,常譯為軟體開發(工具)包
在Win32程式設計領域一般指與MFC這類框架程式設計相區別的,直接呼叫Windows提供的API的開發方式,與字面原意有一些區別。另外一個經常見到的說法就是某軟體(硬體)帶有自己的一套SDK,這裡其實一般是指一套API庫函式或者類庫,供上一層的開發者呼叫。又譬如常說的DX的SDK,其實是微軟開發的一套COM元件,供上層開發者使用。總之,供程式設計師使用的比較完備的程式碼庫,就可以稱之為SDK;
“MFC”: Microsoft Fundation classes 微軟基礎類庫
大家都知道,使用SDK程式設計方式往往有很多每次都重複的固定不變的一些程式碼,為了提高程式設計的效率,減少上千個API帶給開發人員巨大的精神壓力,微軟開發出了這麼一個類庫,注意,這個類庫與作業系統本身無任何關係,它只是對API進行了一個面向物件的封裝,當然,還給出了一系列程式設計的框架。使用SDK的方法,使用Visual Studio,通過呼叫Windows API,MFC你也可以做得出來。MFC把一些固定不變的程式碼已經寫好了,只在編譯時候鏈上,所以我們的程式碼裡看不到WinMain(),而事實上整個程式的執行,和SDK的方式無任何區別,初學者請記住這一點。另,補充一點個人感想,MFC的初衷,帶給開發人員更多的便利,我覺得並不太成功。學習MFC所費的力氣和最終的所得,並不太成正比。
“API”:Application Programming Interface,應用程式介面
這個詞的出現頻率很高,從某種意義上來說,也可以看作是SDK的一個子集。這也是做給程式設計師的程式,不過一般指用匯出函式的方式提供服務的函式庫,不包括類庫和元件。
“GDI”:Graphic Device Interface,圖形裝置介面
這個是Win32程式下最常用的顯示方式,與DirectX、OpenGL處於同一級。在DOS要顯示一些東東可不是容易的事,最簡單的是呼叫一些C的圖形庫函式來實現顯示,不過一般也就是些畫線,填色,輸出幾個文字,效果很弱(所以DOS程式介面一般都不怎麼樣,且實現起來不是一般的複雜),要複雜一點的動畫/圖片顯示什麼的,經常要用到的就是硬體中斷,呼叫一些顯示卡自身的子程式(固化在顯示卡內的)來做。因為每一個顯示卡都不同,所以DOS的遊戲相容常常由於顯示卡的差異而很糟糕。到Windows下大家就幸福多了,Windows將硬體這一層遮蔽起來,用一個表格(Device Context)來代表一個顯示,我們要做的就是在這個表格上填好相關引數,然後畫上我們想畫的東東,然後作業系統會依照這個表格(DC),把相應的顯示內容(一般是一塊顯示記憶體)傳送到指定顯示卡的指定的視訊記憶體,再由顯示卡傳給顯示屏。我們不再需要與不同的顯示卡打交通,這是一個十分偉大的勝利!GDI中最常用的是雙快取技術,就是說你可以在記憶體中建立(也就是複製)一個DC,只不過在這個DC中顯示的不再被傳送到顯示器上。有什麼用呢?因為它的各引數是與當前螢幕DC一致的(COPY嘛 ,當然是這個結果),所以它的顯示內容可以完整無失真地傳送到螢幕DC上。我們通常在記憶體DC上畫圖,譬如畫一圓,再畫一條直線,畫完後一次性地傳送到螢幕DC上,這樣對使用者來說螢幕只重新整理了一次,可以解決你畫一點內容螢幕即重新整理一次導致的閃爍問題。當然,雙緩衝甚至多緩衝還有很多別的用處,那就要靠自己揣摩了。
“DirectX”
通常簡稱為DX(讀音:低叉)這是個很吸引人眼球的名詞,讀起來就很上口:)。Windows為我們作了許多遮蔽底層硬體的工作,其中DX是最知名的技術之一。作業系統要與各類硬體打交道,特別是多媒體相關的,譬如顯示卡、音效卡、手柄輸入、多媒體流的網路傳輸等等,這些事情如果都自己來弄的話,那就太要命了(這些一般都涉及系統底層,自己也很難做出來)。而DX則正是這麼一套作業系統提供的隔離多媒體硬體與程式設計師的間質,DX自身一般並不實現處理的能力,它是一個標準,要求硬體來滿足,好比DX提供一個函式名,硬體來實現函式內容一樣。通過它我們可以非常簡單而快速地呼叫硬體提供的各類服務。它主要包括DirectDraw(通過直接訪問顯示硬體來提供快速的圖象處理能力),DirectSound(提供了軟硬體的低延遲聲音混頻和回放,以及直接訪問音訊裝置的能力),DirectPlay (它明確的提供了通用環境連線能力來簡化你應用程式之間的通訊服務),Direct3D(DirectDraw的3D版),DirectInput(簡化你的應用程式訪問滑鼠、鍵盤和操縱桿裝置的能力),DX5.0之後又增加了一些(如DirectShow),不再詳述。DX一個重要的特點就是你可以通過它直接訪問硬體而無需知道硬體的具體細節。譬如DirectDraw,就能夠越過記憶體而直接訪問視訊記憶體,這樣的速度將比GDI快很多,不在一個數量級上。補充一點:DX是以元件的方式提供的,而不是通常的匯出API的形式。DX SDK的最新版本是9.0
“COM”:component object model,元件物件模型,一般簡稱元件
這是微軟為了解決程式碼重用的一個重要機制。重用程式碼的最簡單辦法是原始碼重用,把寫好的函式和類加到自己當前的程式碼中,編譯即可。簡單是簡單,敝病卻顯然的多。另一個常用的方法是單獨做成模組,以DLL的形式分發,DLL匯出函式或者類,客戶程式用動態/靜態連結的方法將其載入,這顯然比前一種原始碼的方法好一些,難度也不大,最為常用。但DLL也有一些不足,最根本的,它不是二進位制相容,DLL版本升級一次就需要與客戶程式程式碼重連結一次,有些時候這幾乎是不可能的任務。為了更好地讓程式設計像“搭積木”一樣簡單,讓模組可以完美地配合,完美地替換,COM產生了。COM不是類庫,不是程式碼,不是作業系統的服務,而是一套程式設計模型,理論上來說,它與語言無關,與作業系統無關,unix下同樣可以做COM。COM是一種程式結構模型標準,你做的DLL或EXE在結構上滿足這麼一個標準,那這個DLL或EXE就是一個元件,它將在該平臺上成為二進位制相容。COM主要利用了登錄檔來登記本模組的資訊。客戶程式呼叫時首先查登錄檔,找到所需元件的位置(這實現了位置透明),然後就用Loadlibrary把它載入進來,這和普通呼叫沒有本質區別,區別在於由於元件特殊的實現方法使得整個過程中使用者程式都不知道元件的位置,元件的類的例項化過程,如何銷燬,不能直接訪問元件的任何實現細節,使用者只與元件的幾個public介面打交道。這將實現真正的模組之間的獨立。對使用者程式而言,對於目標元件的認識,除了介面,一無所知。在介面不變的情況下,元件可任 意替換而客戶程式不作任何改動,無需編譯,僅這一點,在中大型程式的模組整合的過程中就將節約相當多的時間。
“STL”:Standard Template Library,標準模板庫
這是最早由Alexander Stepanov和Meng Lee(蠻像中國人的名字)完成,於1994年提交給ANSI/ISO 標準C++委員會並通過而成為標準C++的一部分。望文生義即可知這是一個程式碼庫標準,不是語法標準。簡單地說,STL是以C++中的模板語法為基礎建立起來的一套包含基礎資料結構和演算法的程式碼庫。STL的特點是實現了“型別引數化”,即STL的程式碼中可處理任意自定義型別的物件,如果不使用模板技術的話,這是一件相當困難的事。也因為這個原因,在最新的java及C#語法中均加入了對模板語法的支援,可見其重要性。另外一個有關STL重要的話題是GP(Generic Programming),泛型。這是與面向物件相併列的另外的一個程式設計模型,它以模板為基礎,弱化了實體型別的差異,簡化了程式設計時問題抽象的模型,提供了更好的封裝性和彈性,對於繁雜的面向物件程式設計毫無疑問是一種解脫,至少是精神上的。GP並不是用來取代面向物件的,而是作為一個有益的補充體,是面向物件很好的合作伙伴。GP是最近幾年軟體架構的一個研究熱點,但國內真正的應用似乎並不多見,這項技術本身還基本處於研究前沿。<>一書對C++中的GP應用有很好的詮釋,而這本書對腦細胞的殺傷力之大,也是其它C++書藉望塵莫及的。想知道C++的程式碼技巧
可以做到怎樣的出神入化嗎?不妨看看這本書。
“ATL”:Active Template Library,活動模板庫
這在VC程式設計下應該算是比較高階的話題了,它集COM和模板技術於一身,帶來了極方便的元件編寫方法和極高的學習門檻。可以說,進入ATL領域就算是進入了中級以上的程式設計領域。ATL是為元件而生,它的目的是為了讓程式設計師更方便地編寫元件(純用C++寫一個最簡單的元件實現一個“Hello World”對初學者來說都是要命的),同時它使用模板技術來類似於MFC一樣建立了一個開發COM的框架程式碼庫(模板庫),使用該框架及模板庫可以相對方便地進行元件開發。ATL中的一個特點就是你自己的類將成為ATL程式碼庫中某些類的父類,這是一件很有趣的事(這也是模板技術的一個特點)。
“HANDLE”: 控制代碼
這是一箇中文翻譯很古怪的字,對初學者來說是百思不得其解的東東。這其實等價於void*(順便提一下,初學者往往對VC程式碼中各種古怪的符號、型別標記/巨集等百思不得其解,其實它們大多來自基本型別的#define或者typedef,請將游標移到這些符號上(譬如HANDLE),然後按下F12,編譯器自會把你帶到它的宣告處,反覆使用幾次,你終會見到它的原貌,然後長吁一口氣:原來不過如此而已。沒用過的初學者請牢記:F12)。很多初學者總想知道一個HANDLE代表一個什麼物件,我的建議是不要去理解為某物件,而就是理解為訪問某一個物件的入口,事實上HANDLE大多數時候是一個整數索引(標誌該物件在作業系統的某表中的位置,就好像一個數組的下標一樣),Windows系統核心中主要是幾張大表,這樣一個整數索引就是標記目標在這個表中的位置,供作業系統訪問時查詢用。偶而它的確是指向某物件的指標,有時它還攜帶一些額外輔助資訊。總之,我們不要去直接訪問它,把訪問HANDLE的任務交給作業系統好了,除非你還嫌寫程式不累:)。
“DLL”: Dynamic Link Library 動態連結庫
DLL的一個特點就是可以動態載入(顧名思義),即在主程式(我更喜歡稱為客戶程式)需要該模組時才由作業系統載入到記憶體。畢竟一個大型應用程式我們經常使用到的功能並不多,這樣一些不常用的功能模組(DLL)在程式執行時一般將不被載入,可極大節省記憶體開銷。DLL同時也是目前最常用的分發模組的方法,便於彼此協作。程式中對DLL的呼叫主要有兩種方法:1 針對使用DEF檔案匯出函式的DLL,使用API函式LoadLibrary(“DLLModuleName” )載入,然後使用GetProcAddress()得到函式指標,進而呼叫 2 直接將類、函式等匯出,客戶程式使用同一份標頭檔案宣告,加入對應的lib連結庫,即可在客戶程式中直接使用DLL中的類或函式,無需LoadLibrary。
“Process”: 程序
程序是一個動態的概念,包括從程序的建立申請,PCB(Process Control Block程序控制塊,一般作業系統實現為一個表格(struct))的建立,地址空間的記憶體分配,模組程式碼載入並執行,執行完以後進行撤銷,整個過程被稱為”程序”。在Win32下,一個程序有4G的邏輯空間。但我們也常把它作為靜態概念來使用,在Win32下,一個EXE的執行就是一個程序(如果它內部又開了新程序,另當別論)。
“Thread”: 執行緒
為了更有效的提高CPU的利用率,更好地實現多工併發,微軟將程序進行進一步分割,實現了CPU任務排程的新對像:執行緒。一個程序擁有至少一個執行緒。我們在實現多工併發的時候通常是建立一個新執行緒(建立執行緒的系統開銷要小於程序),執行緒以我們自己的一個函式作為入口,函式執行完畢自動撤銷(當然你也可以在執行過程中強制結束該執行緒)。順便提一下,在UNIX下並沒有執行緒這個概念,想來是因為UNIX主要是以多程序的併發服務為主(所以它更適合於做伺服器),系統執行時通常已經有了太多的程序,所以沒有必要再對程序進行細化,因為這樣做甚至會降低系統效率(CPU排程不過來),當然,這是我個人的猜想:)
“C語言”
到目前為止,C語言應該是傳播最為廣泛的語言,特別在UNIX的世界裡依然扮演著主角的位置,在其餘如硬體開發,嵌入式系統(如手機)皆有十分突出的表現,即便在win32平臺下SDK的開發中也有一席之地。更主要的是它是大多數國內(國外我不敢說)程式設計師的啟蒙語言,通過它許多人才領會了程式的思維。C最大的特點就是快,除了彙編以外效率可以達到最高,而它的靈活性,對硬體的直訪性也完全符合程式設計師自由的天性。如果說學習別的技術尚有猶豫和徘徊,那麼學C只有一句話:相信我,沒錯的!也有許多人主張可以直接學習面嚮物件語言,我不太同意。面嚮物件語言對機器模型的抽象十分容易讓程式設計師迷糊,心中難以建立準確的程式執行時的模型。畢竟我們是程式設計師,不是使用者,我們不能把所有的問題都想當然地交給編譯器和作業系統去解決,它們也解決不了。至少學習一門面向過程的語言,才能知其所以然。
C++
這是貝爾實驗室的又一傑作,同時,也傷透了全球太多程式設計師的心,腦細胞殺傷力十分之大。C++比大多數初學者想像的都要複雜得多,它基本包括:一個類化了的C語言,模板,標準模板庫.很多初學者掌握的C++僅僅只是一個類化了的C語言的一個子集(不相信的話,你不妨看一看<>中的C++程式碼,看看能理解多少)。更麻煩的是使用C++不得不談到面向物件的程式設計風格,這同樣比初學者想像的難很多,要有打持久戰的準備。而最讓我這類C++愛好者憂心的還是它目前在Win平臺中的前景,在.net平臺上很難找出不用C#而使用C++寫新程式碼的理由:( 。而它的複雜性和目前許多諸如java/C#及一些動態語言(python/ruby)比起來,開發效率顯然的低,大有退出上層應用程式開發的趨勢。這麼一個包含了最多正規化的近乎完美的語言,我實在不想放棄。我唯有祈禱在未來C++的路可以走得更遠更好一些。
原始碼版本控制
這是軟體開發中一個十分重要的工程手段,幾乎是必須的一個Process(過程)。很多作坊式的開發團隊在採用軟體工程的一些方法的時候,第一個要進行改進或增加的,往往就是這個過程。對初學者學習而言,建議在開始進行實踐小專案的階段即進行原始碼版本控制,因為這在以後的工作中,是一定會用到的。
原始碼版本控制的基本原理如下:
在伺服器端建立該專案的資料庫,並儲存你選定的專案原始檔的第一個版本。客戶端任一使用者要獲得某原始檔的修改權利,需進行check out操作。之後客戶端一般每完成一個無編譯錯誤的版本想儲存的時候,進行check in操作,將當前版本儲存在伺服器端上併成為最新版本(注意,不是覆蓋以前的喲)。任一客戶端可以方便地得到伺服器上的檔案的任意版本(如果有許可權的話)。一般還實現了一個重要的功能是版本比較,任一客戶端可以利用版本控制工具對某檔案的不同版本進行版本比較,它會標記出不同版本的同名檔案的不同點,可以輕易地看出版本內容的演化,這一招很常用。 下面介紹一下我接觸過的三種版本控制工具(也是國內用得比較多的):
VSS: Visual Sourcesafe
這是微軟Visual Studio自帶的原始碼版本控制工具,它最大的特點就是易安裝(與Visual Studio整合在一起,裝VC/VB的時候就順便搞定,不用別外費工夫),使用簡單(伺服器端設定相對容易,一般個人稍加摸索就可以輕鬆搞定,客戶端更是隻管check in/out),基本功能完善,版本比較很直觀(我喜歡)。它的特點是某人check out了某版本以後,別人將無法對此版本check out,也就是說同一時間只有一個可以修改某一個檔案,這樣就避免了不同的人對同一檔案的修改造成彼此衝突(注:可通過設定伺服器端實現多人check out,但幾乎不會這樣做,因為那樣就失去了VSS的一個最重要的功能)。另,VSS可集成於VS環境,但根據我的經驗,直接在VC裡對版本的check操作,常常不生效,所以最好還是到VSS程式裡去進行check操作。補充:單機上也可以使用VSS,這樣的好處是在對當前某些檔案進行了誤操作或大規模地誤修改之後,可以恢復到最近的無錯誤的版本,最大程度地挽回損失。VSS實際應用較普遍,如果你是走Visual Studio路線的話,一定要用一下。
CVS: Concurrent Versions System
這個也是一個大名鼎鼎的開源的版本控制工具,主要活躍在UNIX世界。CVS我使用不多,一般而言好像功能比較偏向於命令列方式(UNIX下開發很多人也都使用著命令列方式)。當然,Windows下面也實現了幾個版本的CVS,也可以集成於VS,好像還有一個可以掛接在IE上的,我沒試過。著名的開源專案管理網站sf.net也是用的CVS,如果你要和全世界的程式設計師一起協作開發,CVS是必須要安裝的。在JAVA的世界裡,也是以CVS為主。
Rational Clearcase
這個工具就比較上檔次了,Rational公司(現在是IBM)的出品,價格昂貴。我最初參加工作的時候用過一小段時間,簡單談一下。這個工具的特點是複雜,安裝及設定就十分複雜,我的印像中客戶端甚至不得不加入到NT域裡面去,導致我在本機的許可權都不夠,安裝新程式都很麻煩,很鬱悶(不知道是不是我們公司的相關人員安裝設定錯了,想來應該是這樣,但其複雜性可見一斑)。對使用而言,它有一個功能挺有用的,就是它能夠根據你每次check的版本號,自動生成版本樹(一個樹狀圖表),你可以清晰地看到版本的演化過程。所以嚴格地說,像CVS/Clearcase這樣的才真正稱得上“版本”控制,VSS還太勉強。Clearcase的功能十分強大,我不詳述了(我還不想出書),較適於大型軟體公司實施軟體配置管理時採用。雖然它的名氣十分之響亮,但我不知道國內有多少公司在真正使用正版的Clearcase這樣的工具,想來應該是十分之少。
OpenGL
OpenGL至今頗有一點英雄落寞的味道,這一套標準是實現得如此之好,以至於曾經一度成為遊戲介面華麗的標準。它的低落也是一個必然,畢竟在微軟的強力打壓下鮮有不挫敗的。但它曾經能夠給微軟帶來如此的壓力,至今也依然在工業界被廣泛使用,大多數遊戲/顯示卡依然保留著對它的支援(CS裡我喜歡的還是OpenGL)。而它的效能在某些方面與D3D比較,依然佔著上風。不幸的是DirectX在不停地向前發展,而它,幾乎止步不前了,前景並不光明。OpenGL目前在工業領域應用較為廣泛,它的優秀的向量圖的操作效能,華麗的色彩,在專業的圖形影象處理領域表現突出。遊戲中使用相對以前而言則是越來越少。新近聽說微軟的最新作業系統Vista對OpenGL進行了極大的打壓,不但效能上折扣,支援的版本也只到1.4(最新版本好像是2.0),不知道最後如何收場,拭目以待。
DirectDraw & D3D
大凡像樣的2維Windows遊戲,幾乎都是採用此技術來實現顯示的。DirectDraw有兩種模式:全屏和視窗。其中全屏應用更多一些。在全屏下,DirectDraw有一個十分著名的“換頁”技術,即在兩個顯示頁面之間用“交換”來實現顯示重新整理,這個速度十分地快,只是一個視訊記憶體內一個指標的交換,比你用BitBlt複製一屏的畫素快太多太多,遊戲的高效的動畫效果大多源於此技術。
DirectDraw主要用於娛樂領域和一些實時顯示要求較高的場合,如醫療影象。D3D是目前大多三維遊戲的標準採用,我沒鑽研過,不敢多言。它的效果嘛,玩玩遊戲就知道了:)
UML:Unified Modeling Language,多譯為統一建模語言
這個語言是一種圖形語言,主要是作為設計時建模的一種標準的圖形模型,便於程式設計師與程式設計師、程式設計師與客戶、設計員與程式碼員之間的溝通,同時它也幫助設計人員將頭腦中的基於程式程式碼的對程式功能的理解形成文件,便於理清頭緒,進行下一步編碼的工作。換言之,設計過程的產品,可以表現為一些文字文件,或者一些框架程式碼,或者一些虛擬碼,但比較標準通用的,是表現為一堆UML圖。UML包括動態圖和靜態圖兩大類,其中靜態圖中的類圖最為常用。很多人初學時不知道該怎麼做設計,寫小軟體時常常沒有設計過程,其實很簡單,把軟體的類圖畫出來就好了。學做設計時未必要找一個像Together或者Rational Rose一樣的巨無霸。用一些簡單的可以做UML圖的工具就好,專門用來畫UML圖的小工具很多,網上容易找。補充一點:畫UML圖不要面面俱到,不要什麼都畫,突出重點方便理解就好,甚至使用不規範的記號也不要緊(當UML的功能是草稿的時候)。
RTTI: Runtime Type Information 執行時型別資訊
在程式中,當我們得到某一個物件的例項或者指標時,大多數時候並不能直接肯定它的型別(都是繼承以及型別轉換惹的禍),這個時候,依靠VC4.0或更高版本的編譯器提供的RTTI支援,呼叫庫函式typeid()即可在執行時獲取這個物件的“型別資訊”,在一些動態處理中“型別資訊”很重要,獲取了型別資訊以後,你就可以有十分把握地呼叫該型別的相關操作,或者型別轉換,或動態生成。因其重要性,在JAVA和.net庫中藉助單根繼承和“虛擬機器”對此有了更優雅的做法,每一個自object繼承的類天然就有了表述自己型別資訊的能力(繼承的好處),並且容易擴充套件,現在你需要型別資訊的時候,大可直接ask那個物件:tell me, what type are you?它就會告訴你答案。
debug & release 除錯 & 發行
大家都知道,debug是除錯版,release是發行版,區別在於debug版生成的程式中包含大量供除錯用的場景程式碼(不是真正執行需要的),而release一般去掉了這些資訊,並進行了某些程式碼優化,所以release版的程式會比debug版的程式小很多,執行速度也快一些。同時,debug版為了便於除錯,往往會對除