Jan 08 2008
《Code Complete》:程式設計者必讀的經典之作
書名:Code Complete, Second Edition
作者:Steve McConnell
譯者:譚詠歸
出版:Microsoft Press; 2nd edition (June, 2004) / 學貫
語言:英文版 / 繁體中文版
Code Complete 是一本很不可思議的好書。書中的內容,沒有模糊不清的理論,而是立即可運用在現行專案或程式中的各種技術。有太多太多的實用知識,完整詳細地解答了我長久以來的疑惑與困擾。
軟體的開發,存在許多不同的階段 (Phase) 與面向,Code Complete 的主要內容,是著重於軟體開發的建構 (Construction) 階段。Construction 一般常會被認為是進行 Coding 或 Programming 的階段;但是在這個階段中,其實還包含了架構設計、細節設計、建構規劃、單元測試等等許多不同的活動程序。
書中的內容從軟體建構的定義開始介紹,從 High-Level 的角度論述「設計」在建構階段中所扮演的角色,與實際可用的設計程序。接著每個章節探討一個主題,由最常見的 Class 與 Routine 設計與實做層面開始,逐步論述各種設計與實做上的考量。而後又討論了 Defensive Programming 與 Pseudocode Programming Process 兩個相當有用的設計方法。
接續的章節往 Low-Level 的建構層面邁進,先以程式中最基本的組成元素,變數的使用開始論述,包括變數的一般使用原則、變數命名、一般資料型態,與非尋常資料型態的變數。變數的設計與使用,經常容易被忽略或是獲得比較少的注意,但是對於一個程式的優劣勝敗來說,變數絕對是具有相當程度的影響力。接著介紹程式中很重要的控制元素,也就是各種控制結構的使用。從直述式結構、條件式結構、迴圈式結構開始,再接續討論非尋常的控制結構、表格驅動方法,與結構式程式設計的一般性原則。結構式程式設計主要的立論在於,無論任何的控制流程,都應該能夠從 Sequence、Selection 與 Iteration 三種架構所建構出來。
接續的章節,再重新回到 High-Level 的觀點, 闡述軟體品質的特徵、專案大小的取捨、建構階段的管理、整合技術,如何深遠地影響到整個專案的運作,與進一步的建構階段。然後是 Developer Testing、Debugging、Refactoring,以及常被過度強調的 Code Tuning 考量與技術。還有一個章節討論較為少見的協同式建構 (Collaborative Construction) 流程。到了書中的最後一個部分,討論的則是比較屬於心理層面的主題,包括很重要也很具爭議性的程式寫作風格與版面配置,以及如何達成不說自明 (Self-Documenting) 的程式碼。最有意思的部分,是書中的最後兩個章節,分別討論了個人特質對於程式建構的影響,與整本書總結整理的部分。
貫穿全書的重要理念主要有以下幾點:
- 克服複雜度:
軟體設計與建構的一個主要目標,就是克服複雜度。 許多程式設計實例背後的動機,都是為了能夠降低程式的複雜度。而降低複雜度,可以說是成為一個有效率的程式設計師,最重要的關鍵。大部分人的思考容量是有限制的,所以我們應該盡力最小化,一個人在同一時間內,需要思考的程式數量。可以說所有軟體設計技術的目標,都是在於將一個複雜的問題,分解成許多簡單的部分。
一個專案的失敗,通常可能是導因自不良的需求、不良的計畫、不良的管理等等因素。但是如果失敗的原因主要是來自技術面的話,那麼這個原因通常是「未被控制的複雜度」(Uncontrolled Complexity)。因此,盡力控制複雜度 (Manage Complexity),可說是在軟體開發中最重要的一項議題。
而一個測量程式複雜度 (Programming Complexity) 的方法,就是你為了瞭解一個程式,而必須在同一時間之內,保持在心裡思考的物件的總數。這種「心智把戲」(Mental Juggling) 的行為,就是程式設計最困難的面向之一,也是程式設計為何需要比其他活動更多專注力的理由之一。有兩個辦法可以對付複雜度: 其一就是藉由更多的「心智練習」以增進操弄心智把戲的能力,然而程式寫作本身就是一件足夠的心智練習,因此能增進的幅度相當有限。其二是降低程式的複雜度,以及為了瞭解它所需要付出的專注力。
根據 Edsger Dijkstra 的論述:大多數的程式設計,都是意圖補償人類極為有限的腦容量。程式設計最佳的人,是那些瞭解他們自己的腦袋有多小的人。他們是謙遜的。學習越多以彌補不足的腦袋容量的人,就會成為越好的程式設計師。越是謙遜的人,越能夠快速的增進。
『Good programmers are humble.』
- 程序 (Process) 的重要性:
在一個小型的專案中,個別程式設計師的才能,是影響軟體品質的最大因素,其中某部分的成功因素,可以歸功於個人選擇使用的程序。然而在比較大型的專案中,相較於個人的技能來說,組織化的特徵程序能夠帶來更大的影響。
即使是一個很好的團隊,他們所能夠貢獻的能力,並不是單純所有個人能力的加總而已。人們在一起工作的方法,會決定他們的能力是有相加的效果,或是相減的效果。程序之所以對於軟體開發很重要的原因,在於品質必須要從軟體專案的第一步就建構於其中。
- 程式撰寫考量的出發點,應該以「人」而非「電腦」做為第一優先考量:
程式碼在很多情況下都會被閱讀,無論是自己或其他人,在修改、除錯、維護的時候,都會需要閱讀程式碼。所以想盡各種辦法,使用各種技術,使程式碼具備可讀性、易讀性是很重要的主題。你應該要花費心力在撰寫良好的程式碼上,以致於你可以只做一次,而非需要重複又重複地閱讀差勁的程式碼。
沒有一個單一技術的應用,可以區別出一個易讀的程式或不易讀的程式,但是由許多小部分閱讀性的改進,能夠累積出重要而可觀的成效。程式設計中,較少部分的工作,是為了撰寫程式讓電腦能夠閱讀它;而較多部分的工作,是在於使得其他的人類能夠閱讀它。因此,程式設計師在撰寫程式的時候,應該要偏好「閱讀時的便利性」,而非「撰寫時的便利性」。
『Any fool can write code that a computer can understand. Good programmers write code that humans can understand.』
- 迭代 (Iterate)、重複:
「設計」是一個奇特的問題 (Design is a wicked problem)。奇特問題 (Wicked Problem) 是指,唯有當這個問題被解決之時,才有辦法清楚的對它做出定義。聽起來像是似是而非的矛盾一樣,而「設計」正是屬於這種類型的奇特問題。設計不會是一開始就如泉湧般直接而完整呈現的,通常會經過許多重複檢視、討論、實做程式碼的經驗後,而逐漸演化與改進的。因此,所謂的設計,其實是一種迭代的過程。
單次的設計通常無法達到最理想的結果;設計本身就是一個不斷反覆琢磨的程序。使用某個方法解決了問題之後,往往可以對這個問題本身獲得更好、更深入的洞察力,可以使我們學習到解決這個問題,更好、更適切的方法。 所以我們可以說,設計本身是一種啟發探索性 (Heuristic) 的程序,而非決定論 (Deterministic) 的程序。這一點,對於軟體專案來說亦然。
最後,作者提到相當重要的一點,就是必須將各種書中的技術視為工具箱中的工具,然後使用自己的判斷,選出適合進行各項工作的工具。這本書裡討論了很多好的程式實例,但不是意指需要拿來當作嚴格遵行的一組標準;而是使用這本書當作討論的基礎,當作良好程式實例的資料全集,以確認出對自己專案最有利的程式實例。
多數的程式設計書籍,都是教導「如何把程式寫好」,然而卻僅有少之又少的書籍教導「如何寫出好程式」。這不是文字上的把戲,而是根本上的不同立足點。一本普通的 C++ 書籍,會教導讀者虛擬與多型的使用語法;一本優秀的 C++ 書籍,會教導讀者虛擬與多型的使用語意;更深入的書籍,或許會教導讀者虛擬與多型背後的設計思維與實做細節。然而,卻鮮少有書籍教導其合適的使用時機,並且能夠和其他可選擇的做法,做優缺點的比較。
什麼樣的情境下使用 Inheritance 會比 Containment 好?到底應該使用繼承類別以達成 Virtual Function 的效用,還是使用 Function Pointer,還是簡單的 Case-Switch?要傳入單一個物件當作參數,還是傳入多個一般資料型態變數當作參數比較合適?要使用深層的巢狀控制結構,還是使用其他控制結構減少巢狀層數?什麼樣的程式才叫做最佳化?怎麼樣才能有效的運用 80/20 法則於最佳化的程序中?還有更多更多可能你我都曾經在腦袋中一閃而過的疑慮。
如果,這本書不能夠提供一個令所有人滿意而一致認同的解答,至少它能夠成為一個驅動思考的啟發點。
Code Complete 目前也有繁體中文版本囉!書名是軟體建構之道。如果你平時的工作非常忙碌,沒有太多時間可以閱讀書籍,一年只能選擇一本書來讀的話,我誠心誠意百分百推薦這本!即使是在兩年多前就閱讀過這本書,現在偶爾拿出當時所做的筆記與摘錄翻閱,仍然能夠從中獲得不少煥然一新的思考啟發與心得印證,絕對是一本值得一讀再讀的好書!

确实是一本非常好的书,可惜我是现在才发现,感觉落后了半个世纪
@chentan:
我當初發現這本書時,也有和你一樣的想法。
只要現在開始讀,就不會太晚。 :)
哈 前幾天去拜了這一本….不過
不知道版大有沒有推薦的遊戲開發知識相關的書籍
廳主管說 只著眼於某一套工具 眼界會太小
本身是想從DirectX開始了解
但是也想知道如果從 遊戲程式開發來說
是看一個學一個 還是有其它方式
因為總絕得 看一個學一個總是很被動
@JK:
基礎的話我推薦這兩本
-Java Game Programming 建立遊戲的演算法與框架
-遊戲之旅 我的程式設計感悟
都是有點早的書,可能不容易買到
第一本雖然是JAVA,不過講到很多遊戲程式的基本觀念,其他語言也適用
遊戲程式開發我覺得是看你想做什麼遊戲再決定研究哪一方面,從底層開始做也一樣
例如文字AVG要有簡單易用的script系統,自己從底層做可以參考NScripter、YU-RIS等引擎的設計
要做彈幕就要研究如何管理大量子彈,以及提升繪圖效能
@Shark:
感謝你!
遊戲之旅這本書我有在天龍查到, 有空會買來看看, 目前書堆的有點多
恩恩, 似乎是明定好目標之後 在朝那著手會比較知道該怎麼作
有時候在作遊戲,總是這邊加點功能,那邊修點bug,後來去玩別人加遊戲
就覺得ㄝ…為啥他這個看起來好漂亮,也好好用,因為遊戲是用script
language開發上層,所以有時候會有底層的限制,後來就去看了底層,
只是因為對引擎的架構不是很熟悉,有時候看了很久才會知到為什麼
需要這些前置作業, 此外,我還想問,就是會有甚麼推薦的方式來增加自己
對於工具上或是知識上的不足嗎?…遊戲這一塊感覺很大,我可以明定
自己要從3D作起,只是 希望平時無聊會逛的網站, 但是不是很清楚
是不是有甚麼人的blog總是會一起分享這些資訊.
我自己是大多都看官方網站, nvidia, python…偶爾會問問同事有
沒有甚麼之類的網站可以參考, 有時候就會發現很多不知道的技術!
遊戲引擎基本架構就是我列的第一本書了,我在博客來看到還有存貨
底層最基本的不外乎繪圖、聲音、輸入三部分
增加知識的方法除了看資料以外,我常常自己寫程式做實驗,像是文字編碼和Unicode我就用printf把每個byte的值印出來研究
另外可以請教一些實際在創作的人
3D最重要的是繪圖流程,繪圖流程熟了再學應用就很容易,不懂的地方就做實驗去試
我研究過3D繪圖流程但沒試過用3D模型畫圖,因為目前沒有要做3D遊戲
這是我知道有在做3D的團隊
http://zestostudio.blogspot.com/
點我的暱稱是我所屬的團隊WKY,要討論我現在在做的東西可以去那裡,在別人的blog討論不太好
@JK:
我認為學習遊戲程式設計的知識,就像是練武功一樣,需要花費許多時間心力勤加練習基本功,一點一滴地累積「內力」,否則就算你學會再多的程式語言、繪圖 API 或遊戲引擎,到頭來可能也只是中看不中用的花拳繡腿而已。
主要還是看你想要朝哪個方向發展。在遊戲程式設計方面,中文的網路資源仍然是少之又少,所以不免還是需要多閱讀國外遊戲開發網站的文章,才能夠獲得第一手的理論與技術資訊。至於書籍的話,如果你想瞭解遊戲系統架構的話,我會推薦《Game Architecture and Design》與《Game Coding Complete》這兩本書。
@Shark:
謝謝你提供的資訊。
感謝! ^_^
@JK:
不客氣~ :)
這本書第兩版我都有買中譯本,
第二版的繁中翻譯得很差,買回來很後悔
同樣是第二版,簡中版就翻譯得比較好,且較便宜
順便一提,
wicked problem 譯成「難纏的問題」或「邪惡的問題」應該比較貼切
我買的第一版是旗標出的,就是譯成「難纏的問題」
@York:
你好,
謝謝你提供的資訊,想購買繁中或簡中版本的讀者可以參考看看~
嗯,wicked problem 翻成「難纏的問題」的確比較貼切。