代碼閱讀

出版時(shí)間:2012-8  出版社:電子工業(yè)出版社  作者:季奧米季斯·斯賓耐立思(Diomidis Spinellis)  頁數(shù):416  譯者:左飛,吳躍,楊寧  
Tag標(biāo)簽:無  

前言

  原作者中文版序  中國是首個(gè)將我的“開源視角”系列作品再版的國家。這可能有很多原因,而其中一個(gè)特別吸引人的原因與孔子的著作有關(guān),他在《論語》中廣泛地強(qiáng)調(diào)了學(xué)習(xí)研究的重要性?;仡欀白珜憽洞a閱讀》和《代碼質(zhì)量》的歷程,我了解到,實(shí)際上,我鼓勵(lì)了那些從事開發(fā)工作的同事和學(xué)生借助研究學(xué)習(xí)軟件代碼來提升他們自身的知識和技能,這正是我遵循孔子金玉良言的一種方式?!  洞a閱讀》一書闡述了開發(fā)者應(yīng)當(dāng)如何閱讀已有的代碼。關(guān)于為何要進(jìn)行代碼閱讀,不少人也給出了許多現(xiàn)實(shí)中的原因:修正問題、添加特性、尋找有用的片段,或者作為你所在機(jī)構(gòu)質(zhì)量控制流程的一部分對其進(jìn)行復(fù)查。然而,進(jìn)行代碼閱讀最重要的原因其實(shí)是從中學(xué)習(xí)。從已有的高質(zhì)量代碼中,我們可以學(xué)習(xí)如何將嚴(yán)謹(jǐn)?shù)拇a風(fēng)格應(yīng)用于實(shí)踐,如何編寫有用的注釋,如何編排代碼以方便他人讀懂,如何選擇有意義的標(biāo)識符,以及如何將復(fù)雜的代碼組織為可管控的部分。另外,通過研究代碼,我們還可以學(xué)習(xí)到新的算法、API及架構(gòu)。簡而言之,閱讀代碼可以幫助我們成為更加優(yōu)秀的程序員。  《代碼質(zhì)量》一書,退后一步,方為大觀。當(dāng)代碼被組裝為程序時(shí)將會產(chǎn)生所謂的聚現(xiàn)屬性:可靠性、安全性、CPU利用率、空間占用率、可移植性及可維護(hù)性。盡管這些屬性可能看起來抽象且難以約束,但是諸多成功的經(jīng)驗(yàn)表明,借助研究專家級的代碼,我們可以學(xué)習(xí)到許多極好的提升代碼質(zhì)量的方法。我們可以從中發(fā)現(xiàn)嚴(yán)謹(jǐn)?shù)腻e(cuò)誤測試、安全證書的保守處理、高效的算法、靈巧的抽象技術(shù)及應(yīng)用于實(shí)踐中的基本設(shè)計(jì)模式。簡而言之,這將有助于我們成為極其優(yōu)秀的程序員?! ゴ蟮恼軐W(xué)家孔子曾經(jīng)提過:“學(xué)而不思則罔,思而不學(xué)則殆”。因此我推薦大家主動花些時(shí)間來研究已有的代碼并從中予以學(xué)習(xí)?! iomidis Spinellis  2011年9月于雅典  推 薦 序  今年恰逢“十二五”開局之年,在全球軟件技術(shù)和產(chǎn)業(yè)格局孕育重大調(diào)整之際,我國軟件產(chǎn)業(yè)也在工業(yè)化、信息化“兩化融合”的大背景下迎來了又一個(gè)快速發(fā)展的新階段,這其中機(jī)遇與挑戰(zhàn)并存。當(dāng)下軟件和信息服務(wù)業(yè)市場的規(guī)模不斷擴(kuò)大,物聯(lián)網(wǎng)作為又一個(gè)萬億元級別的產(chǎn)業(yè)將產(chǎn)生千億元級別的服務(wù)外包。預(yù)計(jì)到2020年,全球潛在的服務(wù)外包市場需求將達(dá)到1.65~1.8萬億美元,大力發(fā)展軟件業(yè)及信息服務(wù)業(yè)將成為各國抓住新機(jī)遇、全面深度參與全球化、提升軟件產(chǎn)業(yè)技術(shù)力量的重要途徑。目前我國軟件產(chǎn)業(yè)規(guī)模雖已過萬億元,但在核心技術(shù)、基礎(chǔ)軟件等方面仍有很大發(fā)展空間?! 「咚刭|(zhì)人才的儲備是推進(jìn)產(chǎn)業(yè)健康快速發(fā)展的根本保證。高端軟件人才的大量持續(xù)涌現(xiàn),關(guān)鍵在于教育,這其中高校無疑要發(fā)揮重要的作用。我們高校軟件教育者既要繼續(xù)貫徹黨的教育理念,進(jìn)一步深化我國高級軟件人才培養(yǎng)體系的發(fā)展進(jìn)程;同時(shí)又要看到我國與歐美等高水平軟件人才教育國家之間的距離,師夷長技,以求在全球化浪潮中謀得一席之地。作為一位優(yōu)秀的軟件教育者,Diomidis Spinellis教授的某些理念無疑是非常值得我們學(xué)習(xí)和借鑒的。他以人類學(xué)習(xí)自然語言的認(rèn)知規(guī)律為出發(fā)點(diǎn),獨(dú)辟新徑,強(qiáng)調(diào)借助代碼閱讀來提高編程能力。目前這一思潮也已逐漸由歐美向我國滲透。  代碼閱讀是每一個(gè)軟件從業(yè)人員經(jīng)常進(jìn)行的活動,其重要性對于每一個(gè)開發(fā)者不言而喻,但人們更多的是在本著修改前人代碼而進(jìn)行此項(xiàng)活動的,換言之,僅僅使用了代碼閱讀的工作屬性,而未見開發(fā)其學(xué)習(xí)屬性。其實(shí),代碼閱讀還幫助人們完成了“觀察-模仿-創(chuàng)造”這樣一個(gè)過程的初始階段。南朝劉勰《文心雕龍》里講“觀千劍而后識器”,與之類似,清乾隆年間蘅塘退士還說“熟讀唐詩三百首,不會作詩也會吟”,這都是強(qiáng)調(diào)了觀察對于之后創(chuàng)造的重要性(巧合的是寫詩和寫代碼的觀察都是借助閱讀來完成的)?! ×钊诉z憾的是,一直以來,許多人都認(rèn)為閱讀代碼不是件容易的事情,不僅不容易,很多時(shí)候還非??菰?;即使是自己寫的代碼,有時(shí)隔一段時(shí)間再回顧也會不知所云。很多人在自己的編碼生涯中都或多或少有過一些閱讀代碼的經(jīng)歷,有自己的一些方法,但也僅僅是一些個(gè)人實(shí)踐而已,缺乏對整體的把握,經(jīng)常是只見樹木不見森林(很多時(shí)候僅僅能看到一小部分樹木)。為了在學(xué)習(xí)的過程中少走一些彎路,業(yè)界代碼閱讀與質(zhì)量提升方面的開宗明義之作--Diomidis Spinellis教授所撰寫的兩部經(jīng)典之作《代碼閱讀》和《代碼質(zhì)量》無疑是推薦給每位從業(yè)人員的理想讀物。這兩部曾榮獲美國Jolt軟件開發(fā)震撼大獎(jiǎng)的作品,影響了一代程序員,是相關(guān)領(lǐng)域中的經(jīng)典名作?! ∥议喿x了兩部書的譯稿,并非常欣喜地將它們推薦給每一位讀者。該書譯者和編輯們嚴(yán)謹(jǐn)、認(rèn)真的工作使得本版最大程度地還原了作者的原意,相信經(jīng)由他們的辛勤努力,必將能為廣大讀者獻(xiàn)上一道驚艷的佳作?! W陽修說:“立身以立學(xué)為先,立學(xué)以讀書為本。”衷心希望廣大讀者借由本書立學(xué)解惑,提升自我?! ±顟?zhàn)懷  于2011歲末  譯 者 序  由國際知名的Addison-Wesley出版社推出的“高效軟件開發(fā)系列”叢書為現(xiàn)代軟件開發(fā)的方方面面提供了專業(yè)的建議和意見。收錄在該系列中的書籍本本都是技術(shù)方面聲名卓著的佳作,這些書籍的作者在創(chuàng)作時(shí)煞費(fèi)苦心,力求作品篇幅適中、易于閱讀,同時(shí)保證作品的價(jià)值能夠歷久彌新,不會隨時(shí)光的流逝而漸顯黯淡。系列中的每一本都描述了一項(xiàng)軟件開發(fā)的核心話題,這些內(nèi)容可能是業(yè)界專家們在開發(fā)中始終秉承的,也可能是需要本書的讀者們引以為戒的,而之所以這樣做,目的只有一個(gè),就是要?jiǎng)?chuàng)造出最杰出的軟件?! ∠ED教授Diomidis Spinellis的兩部著作《代碼閱讀》和《代碼質(zhì)量》均收錄在此系列中。其中,本書作為該領(lǐng)域的開山之作,曾榮獲美國第14屆“軟件開發(fā)”年度震撼大獎(jiǎng)。在IT產(chǎn)業(yè)蓬勃發(fā)展的今日,電子工業(yè)出版社順應(yīng)時(shí)代發(fā)展和廣大讀者希冀,隆重推出了《Jolt獲獎(jiǎng)系列》書叢,《代碼閱讀》和《代碼質(zhì)量》再次被收入其中。經(jīng)典之作《代碼閱讀》得以撥云開霧,同廣大中國讀者見面?! ‘?dāng)今世界,互聯(lián)網(wǎng)迅猛發(fā)展,開源軟件大行其道,海量的優(yōu)質(zhì)代碼猶如一座豐富的寶藏正熱切地等待著每一位開發(fā)人員去發(fā)掘,去閱讀。正如本書英文原版序言的作者Dave Thomas所說的那樣:“沒有哪位偉大的小說家從未讀過其他人的著作,也沒有哪位偉大的畫家從來沒有研究過他人的畫作。”閱讀代碼顯然是每個(gè)軟件開發(fā)人員都必須做的事情。一方面,可能是出于向優(yōu)秀范例程序?qū)W習(xí)的目的,另一方面,也可能是出于代碼復(fù)用的目的。于是,人們總會出于這樣或那樣的原因去閱讀代碼(有可能是別人的,也有可能是自己寫的)。然而,長久以來,“如何正確地閱讀代碼,實(shí)現(xiàn)去粗取精?如何高效地閱讀代碼,做到得心應(yīng)手?”始終沒有一套完備的指導(dǎo)法則?! ≈钡奖緯霈F(xiàn),我們才豁然開朗,原來代碼閱讀也是有章法可依的,也是一門學(xué)問。眾所周知,本書是第一部專門將代碼閱讀作為一項(xiàng)獨(dú)立活動加以論述的書籍,即使在其出版多年之后的今天,也依然是該領(lǐng)域的扛鼎之作。正如本書作者所說的那樣:“代碼閱讀應(yīng)該得到正確地訓(xùn)練,并用做提高編程能力的一種方法。”值得注意的是,目前,在國外先進(jìn)的計(jì)算機(jī)教育體系中,代碼閱讀課程、活動和實(shí)踐已納入到相應(yīng)的正規(guī)課程安排之中?! ≡谥袊?,各大技術(shù)論壇、專業(yè)網(wǎng)站也為廣大從業(yè)人員和程序設(shè)計(jì)愛好者提供了大量可交流的代碼資源。作為譯者,我們真誠地將該書推介給國內(nèi)的讀者,希望借由本書,可以推動開源運(yùn)動,使更多人獲益,也可以推動代碼共享與閱讀的方法與實(shí)踐,提高國人學(xué)習(xí)編程的效率,以期獲得事半功倍的效果?! ≌f到學(xué)習(xí)編程,我不禁想到了最近網(wǎng)上熱炒的“蹭課哥”。據(jù)悉,來自山東菏澤,現(xiàn)年27歲的農(nóng)村青年賈作勝,原本高中畢業(yè)后,由于家庭經(jīng)濟(jì)困難等原因,未能如愿繼續(xù)深造。后來,進(jìn)城打工的他成為了清華大學(xué)的一名普通的保安員。業(yè)余時(shí)間,他一直刻苦學(xué)習(xí),還常到教室旁聽各種課程和名家講座。天道酬勤,今年這位往日的“蹭課哥”,憑借旁聽和自學(xué),考上了山東師范大學(xué)。同樣是保安,我又不禁想到了一個(gè)我身邊的真實(shí)的例子。這個(gè)故事我不止一次講起,還曾經(jīng)在我的一本書的序言里引用過。若干年前,我所在公司樓下有一位與眾不同的小保安。說他與眾不同是因?yàn)楫?dāng)時(shí)經(jīng)常能看到他捧著一本厚厚的《Java編程思想》之類的書在啃讀,這種爭分奪秒、刻苦學(xué)習(xí)的形象當(dāng)時(shí)給我們很多人留下了深刻的印象。功夫不負(fù)有心人,這位保安后來順利轉(zhuǎn)型,成為了一名軟件工程師。  無論是過去還是現(xiàn)在,都有如此之多的形形色色的人因?yàn)楦鞣N原因前仆后繼地在努力鉆研編程。我也曾經(jīng)在文章中指出,研讀他人的代碼是學(xué)習(xí)編程的道路上,除動手實(shí)踐外最重要也最必要的學(xué)習(xí)方法之一。本書的讀者可能已經(jīng)在行業(yè)內(nèi)摸爬滾打多年,也可能初出茅廬,可能是高等院校計(jì)算機(jī)相關(guān)專業(yè)的學(xué)生,也可能只是某個(gè)角落里默默奮發(fā)的小保安。無論你是其中的哪一個(gè),我都真心地希望本書能夠在你成長為編程達(dá)人的道路上助一臂之力。我希望能夠有更多像小保安一樣的人得以華麗轉(zhuǎn)身。若能如此,我心足矣?! 汛е@樣的心情,我們始終秉持著一絲不茍的態(tài)度,力求把經(jīng)典之作原汁原味地帶給中國讀者。而一本專業(yè)技術(shù)領(lǐng)域的譯作得以成功問世,其中之波折也是再所難免。幸得多位業(yè)內(nèi)專家不吝指導(dǎo),使得我們的工作備感鼓舞。在本書翻譯之初,Diomidis Spinellis教授即給我們提出了許多寶貴的建議,他的指導(dǎo)給予了我們極大的幫助。此外,中國計(jì)算機(jī)學(xué)會數(shù)據(jù)庫專業(yè)副主任、西北工業(yè)大學(xué)博士生導(dǎo)師、計(jì)算機(jī)學(xué)院副院長李戰(zhàn)懷教授審閱了譯稿,并欣然為本書作序推薦,感激之情,溢于言表。  本書得以順利付梓,我們還要感謝中國航空工業(yè)集團(tuán)第一飛機(jī)設(shè)計(jì)研究院工程師張貴、西安市公安局網(wǎng)監(jiān)支隊(duì)秦磊、西安交通大學(xué)電信學(xué)院研究生楊驥。三人在各自的技術(shù)方向上擁有豐富的實(shí)踐經(jīng)驗(yàn),其中,張貴曾參與開發(fā)多個(gè)大型飛行模擬器項(xiàng)目,而楊驥和秦磊的研究方向則分別側(cè)重于嵌入式開發(fā)和網(wǎng)絡(luò)安全方面。以上諸位在百忙之中積極參與了本書的翻譯工作,對于他們嚴(yán)肅認(rèn)真的工作態(tài)度,筆者表示由衷敬佩?! ∽罡咂焚|(zhì)的圖書始終是作譯者永恒的追求。但有一千個(gè)讀者,就有一千個(gè)哈姆雷特。因此,我們也真誠地希望本書的讀者能夠把閱讀中的所想所得與我們分享,也歡迎就書中可能存在的紕漏與我們溝通交流,從而使本書日臻完善,以利來者?! ∽箫w  2011年秋

內(nèi)容概要

Jolt大獎(jiǎng)素有“軟件業(yè)之奧斯卡”的美稱,本叢書精選自Jolt歷屆獲獎(jiǎng)圖書,以植根于開發(fā)實(shí)踐中的獨(dú)到工程思想與杰出方法論為主要甄選方向。作者使用了超過600個(gè)現(xiàn)實(shí)的例子來向你展現(xiàn)如何甄別代碼的好壞;如何閱讀,應(yīng)當(dāng)注意什么,以及如何使用這些知識來改進(jìn)自己的代碼。本書在一些現(xiàn)實(shí)中的大型實(shí)例基礎(chǔ)上,論述了代碼閱讀的策略,并向讀者展示了如何將這些代碼閱讀和代碼理解的技藝運(yùn)用于實(shí)踐。

作者簡介

自1985年開始,本書作者Diomidis
Spinellis在開發(fā)大量開創(chuàng)性的,并受到極高評價(jià)的商業(yè)和開源項(xiàng)目的過程中,一直在鉆研、發(fā)展本書中所提及的各項(xiàng)技術(shù),期間他編寫和維護(hù)的代碼行數(shù)超過25萬行。他在英國倫敦帝國理工學(xué)院獲得了軟件工程方向的碩士學(xué)位及計(jì)算機(jī)科學(xué)博士學(xué)位。目前,他是希臘雅典經(jīng)濟(jì)與商業(yè)大學(xué)管理科學(xué)與技術(shù)系的教授。他曾撰寫過多部暢銷世界的計(jì)算機(jī)技術(shù)圖書,包括《架構(gòu)之美》、《代碼質(zhì)量》和《代碼閱讀》等。

書籍目錄

第1章 導(dǎo)論1
1.1 為何以及如何閱讀代碼2
1.1.1 將代碼作為文獻(xiàn)2
1.1.2 將代碼作為范例5
1.1.3 維護(hù)6
1.1.4 演進(jìn)6
1.1.5 重用8
1.1.6 檢查8
1.2 如何閱讀本書9
1.2.1 排版約定9
1.2.2 圖表11
1.2.3 練習(xí)12
1.2.4 輔助材料13
1.2.5 工具13
1.2.6 提綱13
1.2.7 關(guān)于“偉大語言”的爭論14
進(jìn)階閱讀15
第2章 基本編程元素17
2.1 一個(gè)完整的程序17
2.2 函數(shù)和全局變量22
2.3 while循環(huán)、條件和塊26
2.4 switch語句29
2.5 for循環(huán)31
2.6 break和continue語句34
2.7 字符和布爾表達(dá)式36
2.8 goto語句39
2.9 局部重構(gòu)41
2.10 do循環(huán)和整數(shù)表達(dá)式46
2.11 再論控制結(jié)構(gòu)49
進(jìn)階閱讀55
第3章 高級C數(shù)據(jù)類型57
3.1 指針57
3.1.1 鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)58
3.1.2 數(shù)據(jù)結(jié)構(gòu)的動態(tài)分配58
3.1.3 引用調(diào)用59
3.1.4 數(shù)據(jù)元素的訪問60
3.1.5 數(shù)組類型的參數(shù)和返回結(jié)果61
3.1.6 函數(shù)指針63
3.1.7 用做別名的指針65
3.1.8 指針和字符串67
3.1.9 直接內(nèi)存訪問69
3.2 結(jié)構(gòu)體70
3.2.1 組合數(shù)據(jù)元素70
3.2.2 從函數(shù)中返回多個(gè)數(shù)據(jù)元素71
3.2.3 映射數(shù)據(jù)的組織方式71
3.2.4 以面向?qū)ο蠓绞骄幊?3
3.3 聯(lián)合體75
3.3.1 有效利用內(nèi)存空間75
3.3.2 實(shí)現(xiàn)多態(tài)76
3.3.3 不同內(nèi)部表征的訪問77
3.4 動態(tài)內(nèi)存分配79
3.4.1 空閑內(nèi)存管理81
3.4.2 包含動態(tài)分配數(shù)組的結(jié)構(gòu)體83
3.5 typedef聲明85
進(jìn)階閱讀87
第4章 C數(shù)據(jù)結(jié)構(gòu)89
4.1 向量90
4.2 矩陣和表94
4.3 棧98
4.4 隊(duì)列100
4.5 映射103
4.5.1 散列表106
4.6 集合108
4.7 鏈表109
4.8 樹117
4.9 圖122
4.9.1 節(jié)點(diǎn)存儲122
4.9.2 邊的表示124
4.9.3邊的存儲127
4.9.4 圖的屬性129
4.9.5 隱含結(jié)構(gòu)129
4.9.6 其他表示方法130
進(jìn)階閱讀130
第5章 高級控制流程131
5.1 遞歸131
5.2 異常機(jī)制137
5.3 并行性141
5.3.1 硬件和軟件的并行性142
5.3.2 控制模型143
5.3.3 線程實(shí)現(xiàn)148
5.4 信號151
5.5 非局部跳轉(zhuǎn)154
5.6 宏替換157
進(jìn)階閱讀162
第6章 應(yīng)對大型項(xiàng)目163
6.1 設(shè)計(jì)和實(shí)現(xiàn)技術(shù)163
6.2 項(xiàng)目的組織165
6.3 編譯過程與makefile文件172
6.4 配置179
6.5 版本控制184
6.6 項(xiàng)目專用工具191
6.7 測試196
進(jìn)階閱讀203
第7章 編碼規(guī)范和約定205
7.1 文件的名稱和組織206
7.2 縮進(jìn)208
7.3 格式編排210
7.4 命名約定213
7.5 編程實(shí)踐217
7.6 過程規(guī)范219
進(jìn)階閱讀220
第8章 文檔221
8.1 文檔類型221
8.2 閱讀文檔222
8.3 文檔中存在的問題234
8.4 其他文檔來源236
8.5 常見的開源文檔格式239
進(jìn)階閱讀245
第9章 架構(gòu)414
9.1 系統(tǒng)結(jié)構(gòu)248
9.1.1 集中式存儲庫和分布式方法248
9.1.2 數(shù)據(jù)流架構(gòu)252
9.1.3 面向?qū)ο蠼Y(jié)構(gòu)254
9.1.4 分層架構(gòu)257
9.1.5 層次260
9.1.6 切片261
9.2 控制模型263
9.2.1 事件驅(qū)動系統(tǒng)263
9.2.2 系統(tǒng)管理器266
9.2.3 狀態(tài)轉(zhuǎn)移268
9.3 元素包裝270
9.3.1 模塊270
9.3.2 命名空間272
9.3.3 對象276
9.3.4 泛型實(shí)現(xiàn)287
9.3.5 抽象數(shù)據(jù)類型292
9.3.6 庫292
9.3.7 進(jìn)程和過濾器296
9.3.8 組件297
9.3.9 數(shù)據(jù)存儲庫299
9.4 架構(gòu)重用301
9.4.1 框架301
9.4.2 代碼向?qū)?02
9.4.3 設(shè)計(jì)模式303
9.4.4 領(lǐng)域?qū)S械募軜?gòu)305
進(jìn)階閱讀308
第10章 代碼閱讀工具311
10.1 正則表達(dá)式312
10.2 用編輯器瀏覽代碼314
10.3 用grep搜索代碼317
10.4 找出文件的差異325
10.5 開發(fā)自用工具326
10.6 借助編譯器閱讀代碼329
10.7 代碼瀏覽器與美化器333
10.8 運(yùn)行時(shí)工具338
10.9 非軟件工具342
可用工具與進(jìn)階讀物343
第11章 完整示例345
11.1 概況345
11.2 攻克計(jì)劃347
11.3 代碼重用348
11.4 測試與調(diào)試354
11.5 文檔361
11.6 觀察報(bào)告362
附錄A 源代碼致謝人員名單363
附錄B 源代碼致謝人員名單363
附錄C 源代碼致謝人員名單363

章節(jié)摘錄

版權(quán)頁:   插圖:   在分析一個(gè)重要的程序時(shí),最好先找出其最重要的部分。在本例中,這些部分是全局變量(圖2—2:1)和函數(shù)main(圖2—3)、getstops(見圖2—5:1)以及usage(見圖2—5:8)。 整型變量nstops和整型數(shù)組tabstops聲明為全局變量,它們的作用域在函數(shù)體之外。因此,它們對于所分析文件中的所有函數(shù)都是可見的。 緊接著的三個(gè)函數(shù)聲明聲明了該文件內(nèi)之后將出現(xiàn)的函數(shù)。由于其中的一些函數(shù)可能會在其定義之前使用,因此在C/C++程序中,這些聲明允許編譯器校驗(yàn)傳遞給函數(shù)的參數(shù)以及其返回值,并生成相應(yīng)的正確代碼。如果沒有給出前置聲明,那么C編譯器會依據(jù)函數(shù)第一次被使用的情形來做出關(guān)于函數(shù)返回值類型和參數(shù)的假設(shè);C++編譯器將這種情況標(biāo)記為錯(cuò)誤。如果接下來的函數(shù)定義與這些假設(shè)不相符,那么編譯器將給出一條警告或錯(cuò)誤信息。然而,若定義于另一個(gè)文件中的函數(shù)匹配這個(gè)錯(cuò)誤的聲明,則該通過,程序或許能夠編譯,但是在運(yùn)行時(shí)會失敗。 值得注意的是,兩個(gè)函數(shù)被聲明為static,而變量沒有。這就是說這兩個(gè)函數(shù)僅僅在該文件中可見,而那些變量則有可能對組成該程序的所有文件都可見。因?yàn)閑xpand僅由一個(gè)文件組成,所以這一差別在本例中并不重要。多數(shù)連接器(用來合并編譯后的C文件)都十分原始,對所有程序文件都可見的那些變量(即沒有被聲明為static的變量),可能會與定義于其他文件中的同名變量進(jìn)行讓人吃驚的交互。因此,在審查代碼時(shí),最好確保所有只用于單個(gè)文件的變量都聲明為static。 下面一起來看一下組成expand的函數(shù)。想要了解一個(gè)函數(shù)(或方法)在做什么,可以采用如下策略之一。 根據(jù)函數(shù)名猜測。 閱讀函數(shù)開頭的注釋。 分析該函數(shù)是如何被使用的。 閱讀函數(shù)體內(nèi)的代碼。 查詢外部程序文檔。 在本例中,可以很肯定地猜出函數(shù)usage將展示有關(guān)程序用法的信息然后退出;許多命令行程序都有與之具有同樣功能和名稱的函數(shù)。當(dāng)你分析大量的代碼時(shí),你將會逐漸得出變量和函數(shù)的名稱以及命名規(guī)范。這些將會幫助你正確的猜出它們的用途。然而,你應(yīng)當(dāng)做好準(zhǔn)備,根據(jù)代碼閱讀過程中必然會出現(xiàn)的一些新證據(jù)來隨時(shí)對最初的猜測做出修改。另外,基于猜測修改代碼時(shí),應(yīng)當(dāng)設(shè)計(jì)一個(gè)流程來驗(yàn)證最初的假設(shè)。這一流程可以包括用編譯器檢查、引入斷言或執(zhí)行恰當(dāng)?shù)臏y試用例。 getsopts的角色比較難于理解。這里沒有任何注釋,函數(shù)體中的代碼比較復(fù)雜,其名稱也可以多種方式解讀。注意它被用在程序中一個(gè)單獨(dú)的部分(圖2—3:3),這可以幫助我們做進(jìn)一步的分析。使用到getopt的部分在程序中負(fù)責(zé)處理程序選項(xiàng)(圖2—3:2)。因此,可以肯定地(在本例中也是正確地)認(rèn)為getopt將處理制表位說明選項(xiàng)。在閱讀代碼時(shí),這種漸進(jìn)式的理解較為常見;理解了某一部分的代碼可以使得其他部分變得容易理解。基于這種漸進(jìn)式的理解方式,在理解較為困難的代碼時(shí),可以采用類似組合拼圖游戲時(shí)的策略:從容易的部分開始。

編輯推薦

《Jolt大獎(jiǎng)精選叢書:代碼閱讀》榮獲2003年Jolt世界圖書大獎(jiǎng),參閱《代碼閱讀》對于大專院校相關(guān)專業(yè)的師生、計(jì)算機(jī)領(lǐng)域的從業(yè)人員或稗序設(shè)計(jì)愛好者都大有裨益。

圖書封面

圖書標(biāo)簽Tags

評論、評分、閱讀與下載


    代碼閱讀 PDF格式下載


用戶評論 (總計(jì)34條)

 
 

  •   雖然書中很多內(nèi)容是跟C系統(tǒng)語言相關(guān)的東西,但是整體來說,確實(shí)在代碼閱讀經(jīng)驗(yàn)上給出了作者自己的經(jīng)驗(yàn),很好
  •   學(xué)會讀一些代碼~對于以后coding具有很重要的意義~這本書就告訴了我coding好的代碼
  •   書的內(nèi)容沒得說,送貨速度也很快,上午訂的下午就到了,只是書上的土太多了,不太舒服。此書中包括一張光盤,有很多的開源項(xiàng)目的源代碼,可以通過讀書以及代碼學(xué)到不少東西,看看大牛們都是如何寫程序的。
  •   好書,還沒看,認(rèn)真閱讀中。
  •   比原版的有改進(jìn),更加與時(shí)俱進(jìn)。
  •   這本書不錯(cuò),對一線的人員很有用,對教師也很有啟發(fā)性。
  •   據(jù)同事說還是不錯(cuò),我是沒看懂
  •   還沒仔細(xì)去看,不過感覺還不錯(cuò)。
  •   重在實(shí)踐哈
  •   書里的例子大多是C語言的,提到的編碼規(guī)范,架構(gòu)重用,測試調(diào)試都很有參考價(jià)值。
  •   還沒讀,大至看了一下,還不錯(cuò)。
  •   書像舊書,快遞送過來水淋淋的,都沒有閱讀的興趣了
  •   就這本書來說,感覺對于沒有太多編程經(jīng)驗(yàn)的人來說,是沒啥用的。
  •   書的第一頁是壞的 光盤是壞的 打開包裹的時(shí)候有點(diǎn)郁悶不過書的內(nèi)涵還是挺不錯(cuò)的,是大師級人物寫的書
  •   對閱讀和接手現(xiàn)項(xiàng)目很有用,還對于迅速定位Bug莫大的幫助
  •   這是一本和Kent Beck理念相反的書,指導(dǎo)人們?nèi)绾伍喿x作為機(jī)器語言的代碼而非把代碼像寫故事一樣讓人容易閱讀。讀了一些,我個(gè)人感覺不知所云,可能因?yàn)閷懘a的總量太少,體會不到作者的專業(yè)精神
  •   一整套的,應(yīng)該很好
  •   好書,初看了前面幾頁還行
  •   教你怎么閱讀代碼
  •   到貨快,購書方便
  •   書籍很好都是正版的。
  •   復(fù)習(xí)了一下 C 的知識,還行
  •     代碼閱讀有自身的一套技能,重要的是能夠確定什么時(shí)候使用哪項(xiàng)技術(shù)。本書中,作者使用600多個(gè)現(xiàn)實(shí)的例子,向讀者展示如何區(qū)分好的(和壞的)代碼,如何閱讀,應(yīng)該注意什么,以及如何使用這些知識改進(jìn)自己的代碼。養(yǎng)成閱讀高品質(zhì)代碼的習(xí)慣,可以提高編寫代碼的能力。    閱讀代碼是程序員的基本技能,同時(shí)也是軟件開發(fā)、維護(hù)、演進(jìn)、審查和重用過程中不可或缺的組成部分。本書首次將閱讀代碼作為一項(xiàng)獨(dú)立課題,系統(tǒng)性地加以論述。本書引用的代碼均取材于開放源碼項(xiàng)目——所有程序員都應(yīng)該珍視的寶庫。本書圍繞代碼閱讀,詳細(xì)論述了相關(guān)的知識與技能。“他山之石、可以攻玉”,通過仔細(xì)閱讀并學(xué)習(xí)本書,可以快速地提高讀者代碼閱讀的技能與技巧,進(jìn)而從現(xiàn)有的優(yōu)秀代碼、算法、構(gòu)架、設(shè)計(jì)中汲取營養(yǎng),提高自身的開發(fā)與設(shè)計(jì)能力。    本書適用于對程序設(shè)計(jì)的基本知識有一定了解,并想進(jìn)一步提高自身開發(fā)能力的讀者。
  •      代碼閱讀方法與實(shí)踐 Code Reading: The Open Source Perspective http://www.spinellis.gr/codereading/
      
      
      第零章 綜述
      提高代碼閱讀的技能與技巧,進(jìn)而從現(xiàn)有的優(yōu)秀代碼、算法、架構(gòu)、設(shè)計(jì)中汲取營養(yǎng),提高自身的開發(fā)與設(shè)計(jì)能力。
      恐怕沒有哪個(gè)偉大的小說家從未讀過其他人的著作,沒有哪個(gè)偉大的畫家從未研究過他人的繪畫作品,沒有哪個(gè)技術(shù)熟練的外科醫(yī)生從未觀摩過同事如何動手術(shù),沒有哪個(gè)播音767的機(jī)長不是首先在副駕駛員的位置上觀看如何實(shí)際操作的。
      可是,現(xiàn)實(shí)卻期望程序員能夠做到這些(即,不用讀他人的代碼就能夠編寫出優(yōu)秀的代碼。)
      《Unix操作系統(tǒng)注釋》、Apache Web服務(wù)器、Perl語言、GNU/Linux操作系統(tǒng)、BIND域名服務(wù)器和sendmail郵件傳輸代理程序
      與代碼相關(guān)的大部分概念:包括變成構(gòu)造、數(shù)據(jù)類型、數(shù)據(jù)結(jié)果、控制流程、項(xiàng)目組織、代碼規(guī)范、文檔和構(gòu)架
      另外一本是介紹:接口和面向應(yīng)用的代碼包括國際化和可移植性問題,常用庫和操作系統(tǒng)中的元件、低級嗲嗎、領(lǐng)域?qū)S械穆暶餍哉Z言、腳步語言和混合語言系統(tǒng)。
      
       第一章 導(dǎo)論
      1.1 為什么以及如何閱讀代碼
      1.1.1 將代碼作為文獻(xiàn)
      1. 要養(yǎng)成一個(gè)習(xí)慣,經(jīng)?;〞r(shí)間閱讀別人編寫的高品質(zhì)代碼。 (讀好書、多讀書) 就像閱讀高品質(zhì)的散文能夠豐富詞匯、激發(fā)想象力、擴(kuò)展思維一樣,分析設(shè)計(jì)良好的軟件系統(tǒng)的內(nèi)部結(jié)構(gòu)可以學(xué)到新的架構(gòu)模式、數(shù)據(jù)結(jié)構(gòu)、編碼方法、算法、風(fēng)格和文檔規(guī)范、應(yīng)用程序編程接口(API),甚至新的計(jì)算機(jī)語言。閱讀高品質(zhì)的代碼還可以提高您編寫代碼的水準(zhǔn)。
      
      2. 要有選擇地閱讀代碼,同時(shí),還要有自己的目標(biāo)。您是想學(xué)習(xí)新的模式、編碼風(fēng)格、還是滿足某些需求的方法?或者,您也許只是在瀏覽代碼,獲得其中的某些亮點(diǎn)。在這種情況下,要隨時(shí)準(zhǔn)備仔細(xì)地研究那些有趣但尚不了解的部分:語言特性(即使您對一種語言了解得很透切,也不可能盡知它的所有特性,因?yàn)楝F(xiàn)代語言的發(fā)展離不開新特性,新的特性總是不斷涌現(xiàn))、API、算法、數(shù)據(jù)結(jié)構(gòu)、架構(gòu)和設(shè)計(jì)模式(design pattern) (搞清楚為什么要閱讀代碼? 學(xué)習(xí)架構(gòu)、學(xué)習(xí)業(yè)務(wù)、學(xué)習(xí)模式、學(xué)習(xí)編碼風(fēng)格、學(xué)習(xí)類庫... ... 制定目標(biāo),對自己要有要求)
      
      3. 要注意并重視代碼中特殊的非功能性需求,這些需求也許會導(dǎo)致特定的實(shí)現(xiàn)風(fēng)格。對可移植性、時(shí)間或空間效率、易讀性、甚至迷惑性的需求都可能導(dǎo)致代碼具有非常特殊的特征(如 可維護(hù)性、可伸縮性、性能、)
      
      一種積極地閱讀代碼的方式主動的修改代碼來檢驗(yàn)?zāi)鷮Υa的理解是否正確。再次強(qiáng)調(diào),要從小的改動做起,逐漸地增大他們的范圍。通過積極地介入現(xiàn)實(shí)的代碼,您能夠快速地從中了解到新環(huán)境的一些基本情況。當(dāng)您認(rèn)為已經(jīng)掌握了他們之后,要考慮投入一些努力(可能要需要投入一些資金)、采取更優(yōu)組織的方式來學(xué)習(xí)該環(huán)境。閱讀相關(guān)的書籍、文檔或手冊,或者參加培訓(xùn)課程;這兩種學(xué)習(xí)方式互相補(bǔ)充。
      另一種積極地閱讀現(xiàn)有代碼(作為文獻(xiàn))的方式是改進(jìn)它。如果代碼對您或您的團(tuán)體有價(jià)值,請考慮如何來改進(jìn)它。這可能涉及到使用更好的設(shè)計(jì)或算法、為某些代碼編制文檔,或增加功能。開放源代碼項(xiàng)目中的代碼常常沒有很好地編制文檔;請將您對代碼的理解應(yīng)用到改進(jìn)文檔上。
      4. 在現(xiàn)有的代碼上工作時(shí),請與作者或維護(hù)人員進(jìn)行必須的協(xié)調(diào),以避免重復(fù)勞動或因此而產(chǎn)生厭惡情緒。
      
      5. 如果您的更難該更為健壯,則考慮申請成為一個(gè)版本控制系統(tǒng)的提交者----擁有直接向項(xiàng)目的源代碼庫中提交代碼的授權(quán)。請將從開放源碼軟件中得到的益處看作是一項(xiàng)貸款,盡可能地尋找各種方式來回報(bào)開放源碼社團(tuán)。(比如、報(bào)告bug,提出問題,解決bug,添加功能貢獻(xiàn)代碼及文檔... ... 人人為我,我為人人)
      
      1.1.2 以代碼為范例
      6. 想要了解一個(gè)特定的功能是如何實(shí)現(xiàn)的。對于某些類型的應(yīng)用,您也許能夠在普通的書籍或?qū)I(yè)的出版物和研究論文中得出問題的答案,然而,多數(shù)情況下,如果您想要了解“別人會如何完成這個(gè)功能呢?”,除了閱讀代碼以外,沒有更好的方法。
      
      1.1.3 維護(hù)
      7. 在尋找BUG時(shí),請從問題的表現(xiàn)形式到問題的根源來分析代碼。不要沿著不相關(guān)的路徑(誤入岐途) (先搞清楚問題,然后找與問題相關(guān)部分代碼閱讀,記住帶有目的性的閱讀)
      
      8. 尋找bug,這種情況下,關(guān)鍵的思想是使用工具,我們要充分利用調(diào)試器,編譯器給出的警告或輸出的符號代碼,系統(tǒng)調(diào)用跟蹤器,數(shù)據(jù)庫結(jié)構(gòu)化查詢語言(SQL)的日志機(jī)制、包轉(zhuǎn)儲工具和Windows的消息偵查程序,定出BUG的位置。(要充分利用線索。 偵探破案、醫(yī)生診斷 都是利用線索或現(xiàn)象的)
      
      1.1.4 演進(jìn)
      9. 對于那些大型且組織良好的系統(tǒng),您只需要最低限度地了解它的全部功能,就能夠?qū)λ龀鲂薷?。(一個(gè)系統(tǒng)可能有幾十個(gè)模塊,只需要了解與問題相關(guān)的模塊,就有可能把問題解決,但首先必須模塊設(shè)計(jì)合理)
      10. 當(dāng)向系統(tǒng)中增加新功能時(shí),首先的任務(wù)就是找到實(shí)現(xiàn)類似特性的代碼,將它作為待實(shí)現(xiàn)功能的模板。(做一個(gè)新功能首先考慮到的是有沒有類似的 模板或例子,有類似模板或例子可以提供借鑒,讓你如何實(shí)現(xiàn)該功能有更加深入的認(rèn)識)
      11. 從特性的功能描述到代碼的實(shí)現(xiàn),可以按照字符串消息,或使用關(guān)鍵詞來搜索代碼。
      12. 在移植代碼或修改接口時(shí), 您可以通過編譯器直接定位出問題涉及的范圍,從而減少代碼閱讀的工作量。
      13. 進(jìn)行重構(gòu)時(shí),您從一個(gè)能夠正常工作的系統(tǒng)開始做起,希望確保結(jié)束時(shí)系統(tǒng)能夠正常工作。一套恰當(dāng)?shù)臏y試用例可以幫助您滿足此項(xiàng)約束。(測試用例很關(guān)鍵)
      14. 閱讀代碼尋找重構(gòu)機(jī)會時(shí),先從系統(tǒng)的構(gòu)架開始,然后逐步細(xì)化,能夠獲得最大的效益。(由宏觀到微觀,由上到下一種方法)
      1.1.5 重用
      15. 代碼的可重用性是一個(gè)誘人的,但難以掌握的思想;降低期望就不會感到失望。軟件部件一般要經(jīng)過逐漸地?cái)U(kuò)展,并重復(fù)改寫以適用于兩個(gè)或三個(gè)不同系統(tǒng)之后,才會成為可重用的部件;
      16. 如果您希望重要的代碼十分棘手,難以理解與分離,可以試著尋找粒度更大一些的包,甚至其他代碼。
      1.1.6 審查
      17. 在復(fù)查軟件系統(tǒng)時(shí),要注意,系統(tǒng)是由很多部分組成的,不僅僅只是執(zhí)行語句。還要注意分析以下內(nèi)容:文件和目錄結(jié)構(gòu)、生成和配置過程、用戶界面和系統(tǒng)的文檔。
      18. 可以將軟件復(fù)查作為一個(gè)學(xué)習(xí)、講授、援之以手和接受幫助的機(jī)會。
      
      1.2 如何閱讀本書
      1.2.1 印刷約定
      1.2.2 圖解UML
      1.2.3 練習(xí)
      1.2.4 輔助材料
       《代碼閱讀方法與實(shí)踐》(Code Reading: The Open Source Perspective)中文版[更新CD-ROM] http://www.chnp2p.com/viewthread.php?tid=559279
       隨書光盤下載:http://www.ugcn.cn/bencandy.php?fid=231&id=168263
       http://www.spinellis.gr/codequality/
      1.2.5 工具
       Linux下工具:grep find
      1.2.6 大綱
      1.2.7 “重要語言”的爭論
       開放源碼下載地址: http://sourceforge.net/directory/
      1.2.8 進(jìn)階讀物
      
      
       第二章 文檔(原書:第八章:文檔)P196
      
      150.閱讀代碼時(shí), 應(yīng)該盡可能地利用任何能夠得到的文檔.
      
      151.閱讀一小時(shí)代碼所得到的信息只不過相當(dāng)于閱讀一分鐘文檔.
      
      
      8.1 文檔的類型
      152.使用系統(tǒng)的規(guī)格說明文檔(system specification document), 詳細(xì)描述系統(tǒng)的目標(biāo)、系統(tǒng)的功能需求、管理和技術(shù)上的限制、以及成本和日程等要素,了解所閱讀代碼的運(yùn)行環(huán)境.
      153.軟件需求規(guī)格說明(software requirements specification)提供對用戶需求和系統(tǒng)總體結(jié)構(gòu)的高層描述,并且詳細(xì)記述系統(tǒng)的功能和非功能性需求,比如數(shù)據(jù)處理、外部接口、數(shù)據(jù)庫的邏輯模式以及設(shè)計(jì)上的各種約束。由于軟硬件環(huán)境和用戶需求的不斷改變,文檔中還可能描述預(yù)期的系統(tǒng)演化。是閱讀和評估代碼的基準(zhǔn).
      154.系統(tǒng)的設(shè)計(jì)規(guī)格說明(system design specification)一般描述系統(tǒng)的構(gòu)架、數(shù)據(jù)和代碼結(jié)構(gòu),還有不同模塊之間的接口。面向?qū)ο蟮脑O(shè)計(jì)會勾畫出系統(tǒng)的基本類型以及公開方法。細(xì)化的設(shè)計(jì)規(guī)格一般還包括每個(gè)模塊(或類)的具體信息,比如它執(zhí)行的處理任務(wù)、提供的接口,以及與其他模塊或類之間的關(guān)系。另外,設(shè)計(jì)規(guī)格說明還會描述系統(tǒng)采用的數(shù)據(jù)結(jié)構(gòu),適用的數(shù)據(jù)庫模式等。系統(tǒng)的設(shè)計(jì)規(guī)格說明作為認(rèn)知代碼結(jié)構(gòu)的路線圖, 閱讀具體代碼的指引.
      155.系統(tǒng)測試規(guī)格說明(system test specification)包括測試計(jì)劃、具體的測試過程、以及實(shí)際的測試結(jié)果。每個(gè)測試過程都會詳細(xì)說明它所針對的模塊以及測試用例使用的數(shù)據(jù)(從中可以得知特定的輸入由哪個(gè)模塊處理)。利用測試規(guī)格說明文檔為我們提供可以用來預(yù)演正在閱讀的代碼.
      用戶文檔(user documentation),這些文檔包括功能描、安裝說明、介紹性的引導(dǎo)、參考手冊和管理員手冊。
      156.在接觸一個(gè)未知系統(tǒng)時(shí), 功能性的描述和用戶指南可以提供重要的背景信息,從而更好地理解閱讀的代碼所處的上下文.
      
      157.從用戶參考手冊中, 我們可以快速地獲取, 應(yīng)用程序在外觀與邏輯上的背景知識, 從管理員手冊中可以得知代碼的接口|文件格式和錯(cuò)誤消息的詳細(xì)信息.
      
      
      8.2 閱讀文檔
      158.利用文檔可以快捷地獲取系統(tǒng)的概況, 了解提供特定特性的代碼.
      159.文檔經(jīng)常能夠反映和提示出系統(tǒng)的底層結(jié)構(gòu).
      160.文檔有助于理解復(fù)雜的算法和數(shù)據(jù)結(jié)構(gòu).
      161.算法的文字描述能夠使不透明(晦澀, 難以理解)的代碼變得可以理解.
      162.文檔常常能夠闡明源代碼中標(biāo)識符的含義.
      163.文檔能夠提供非功能性需求背后的理論基礎(chǔ).
      164.文檔還會說明內(nèi)部編程接口.
      165.由于文檔很少像實(shí)際的程序代碼那樣進(jìn)行測試, 并受人關(guān)注, 所以它常常可能存在錯(cuò)誤|不完整或過時(shí).
      166.文檔也提供測試用例, 以及實(shí)際應(yīng)用的例子.
      167.文檔常常還會包括已知的實(shí)現(xiàn)問題或bug.
      168.環(huán)境中已知的缺點(diǎn)一般都會記錄在源代碼中.
      169.文檔的變更能夠標(biāo)出那些故障點(diǎn).一般命名為ChangeLog
      170.對同一段源代碼重復(fù)或互相沖突的更改, 常常表示存在根本性的設(shè)計(jì)缺陷, 從而使得維護(hù)人員需要用一系列的修補(bǔ)程序來修復(fù).
      171.相似的修復(fù)應(yīng)用到源代碼的不同部分, 常常表示一種易犯的錯(cuò)誤或疏忽, 它們同樣可能會在其他地方存在.
      
      8.3 文檔存在的問題
      172.文檔常常會提供不恰當(dāng)?shù)男畔? 誤導(dǎo)我們對源代碼的理解. 兩種不同類型的歪曲是未記錄的特性(undocumented feature)和理想化表述(idealized presentation)
      173.要警惕那些未歸檔的特性: 將每個(gè)實(shí)例歸類為合理|疏忽或有害, 相應(yīng)地決定是否應(yīng)該修復(fù)代碼或文檔.
      174.有時(shí), 文檔在描述系統(tǒng)時(shí), 并非按照已完成的實(shí)現(xiàn), 而是系統(tǒng)應(yīng)該的樣子或?qū)淼膶?shí)現(xiàn)即理想化表述(idealized presentation).
      175.在源代碼文檔中, 單詞gork的意思一般是指”理解”.
      176.如果未知的或特殊用法的單詞阻礙了對代碼的理解, 可以試著在文檔的術(shù)語表(如果存在的話)|New Hacker’s Dictionary[Ray96]|或在Web搜索引擎中查找它們.
      
      8.4 其他文檔來源
      177.總是要以批判的態(tài)度來看待文檔, 注意非傳統(tǒng)的來源, 比如注釋|標(biāo)準(zhǔn)|出版物|測試用例|郵件列表|新聞組|修訂日志|問題跟蹤數(shù)據(jù)庫|營銷材料|源代碼本身.
      178.總是要以批判的態(tài)度來看待文檔; 由于文檔永遠(yuǎn)不會執(zhí)行, 對文檔的測試和正式復(fù)查也很少達(dá)到對代碼的同樣水平, 所以文檔常常會誤導(dǎo)讀者, 或者完全錯(cuò)誤.
      179.對于那些有缺陷的代碼, 我們可以從中推斷出它的真實(shí)意圖.
      
      8.5 常見的開發(fā)源代碼文檔格式
      文檔兩種類型:
       1 二進(jìn)制文件:他們的生成和閱讀都要使用專利產(chǎn)品,如:Microsoft Word或Adobe FrameMaker;
       2 文本文件:其中包含標(biāo)記語言(markup language)形式的結(jié)構(gòu)和格式化命令。
       2.1 troff 2.2 Texinfo 2.3 DocBook 2.4 javadoc 2.5 Doxygen 2.6 Unix手冊頁 2.7 javadoc注釋 2.8 Texinfo文檔 2.9 DocBook
      
      180.在閱讀大型系統(tǒng)的文檔時(shí), 首先要熟悉文檔的總體結(jié)構(gòu)和約定.
      
      181.在對付體積龐大的文檔時(shí), 可以使用工具, 或?qū)⑽谋据敵龅礁咂焚|(zhì)輸出設(shè)備上, 比如激光打印機(jī), 來提高閱讀的效率.
      
      
      8.6 進(jìn)階讀物
      
       第三章 系統(tǒng)構(gòu)架(原書:第九章: 系統(tǒng)構(gòu)架)、設(shè)計(jì)模式、編碼慣例
      
      9.1 系統(tǒng)的結(jié)構(gòu)
       9.1.1 集中式存儲庫(centralized repository)和分布式方案(distributed Scheme)
      182.一個(gè)系統(tǒng)可以(在重大的系統(tǒng)中也確實(shí)如此)同時(shí)展示出多種不同的構(gòu)架類型. 以不同的方式檢查同一系統(tǒng)、分析系統(tǒng)的不同部分、或使用不同級別的分解, 都有可能發(fā)現(xiàn)不同的構(gòu)架類型.
      183.協(xié)同式的應(yīng)用程序, 或者需要協(xié)同訪問共享信息或資源的半自治進(jìn)程, 一般會采用集中式儲存庫構(gòu)架.
      184.黑板系統(tǒng)使用集中式的儲存庫, 存儲非結(jié)構(gòu)化的鍵/值對, 作為大量不同代碼元件之間的通信集線器.
      
      9.1.2 數(shù)據(jù)流構(gòu)架(data-flow)
      185.當(dāng)處理過程可以建模|設(shè)計(jì)和實(shí)現(xiàn)成一系列的數(shù)據(jù)變換時(shí), 常常會使用數(shù)據(jù)流(或管道—過濾器)構(gòu)架.
      186.在批量進(jìn)行自動數(shù)據(jù)處理的環(huán)境中, 經(jīng)常會采用數(shù)據(jù)流構(gòu)架, 在對數(shù)據(jù)工具提供大量支持的平臺上尤其如此.
      187.數(shù)據(jù)流構(gòu)架的一個(gè)明顯征兆是: 程序中使用臨時(shí)文件或流水線(pipeline)在不同進(jìn)程間進(jìn)行通信.
      
      9.1.3 面向?qū)ο蟮慕Y(jié)構(gòu)(object-oriented)
      188.使用圖示來建模面向?qū)ο髽?gòu)架中類的關(guān)系.
      189.可以將源代碼輸入到建模工具中, 逆向推導(dǎo)出系統(tǒng)的構(gòu)架.
      
      9.1.4 分層構(gòu)架(layered)
      190.擁有大量同級子系統(tǒng)的系統(tǒng), 常常按照分層構(gòu)架進(jìn)行組織.
      191.分層構(gòu)架一般通過堆疊擁有標(biāo)準(zhǔn)化接口的軟件組件來實(shí)現(xiàn).
      192.系統(tǒng)中每個(gè)層可以將下面的層看作抽象實(shí)體, 并且(只要該層滿足它的需求說明)不關(guān)心上面的層如何使用它.
      193.層的接口既可以是支持特定概念的互補(bǔ)函數(shù)族, 也可以是一系列支持同一抽象接口不同底層實(shí)現(xiàn)的可互換函數(shù).
      194.用C語言實(shí)現(xiàn)的系統(tǒng), 常常用函數(shù)指針的數(shù)組, 表達(dá)層接口的多路復(fù)用操作.
      195.用面向?qū)ο蟮恼Z言實(shí)現(xiàn)的系統(tǒng), 使用虛方法調(diào)用直接表達(dá)對層接口的多路復(fù)用操作.
       9.1.5 層次(hierarchical decompositon)
      
      196.系統(tǒng)可以使用不同的、獨(dú)特的層次分解模型跨各種坐標(biāo)軸進(jìn)行組織.
       系統(tǒng)的層次結(jié)構(gòu):
       源代碼在目錄中的安排
       靜態(tài)或動態(tài)過程調(diào)用圖
       namespace(C++),package(Ada,Java,Perl),或標(biāo)識符名稱
       類和接口的繼承關(guān)系
       結(jié)構(gòu)化黑板項(xiàng)(blackboard entry)的命名
       內(nèi)部類和嵌套過程
       異構(gòu)數(shù)據(jù)結(jié)構(gòu)和對象關(guān)聯(lián)中的導(dǎo)航
      
      9.1.6 切片(slicing)
      197.使用程序切片技術(shù), 可以將程序中的數(shù)據(jù)和控制之間依賴關(guān)系集中到一起.切片可以對量模塊內(nèi)聚性。
      
      9.2 控制模型
       系統(tǒng)的控制模型描述構(gòu)成系統(tǒng)的各個(gè)子系統(tǒng)之間如何進(jìn)行交互。
       9.2.1 事件驅(qū)動的系統(tǒng)(event-driven architecture)
       9.2.2 系統(tǒng)管理器(system manager control model)
      198.在并發(fā)系統(tǒng)中, 一個(gè)單獨(dú)的系統(tǒng)組件起到集中式管理器的作用, 負(fù)責(zé)啟動、停止和協(xié)調(diào)其他系統(tǒng)進(jìn)程和任務(wù)的執(zhí)行.
      199.許多現(xiàn)實(shí)的系統(tǒng)都會博采眾家之長. 當(dāng)處理此類系統(tǒng)時(shí), 不要徒勞地尋找無所不包的構(gòu)架圖; 應(yīng)該將不同構(gòu)架風(fēng)格作為獨(dú)立但相關(guān)的實(shí)體來進(jìn)行定位|識別并了解.
      
      9.2.3 狀態(tài)變遷(state transition model)
      狀態(tài)變遷模型(state transition model)通過操作數(shù)據(jù)----系統(tǒng)的狀態(tài),來管理系統(tǒng)的控制流程。狀態(tài)數(shù)據(jù)決定執(zhí)行控制權(quán)應(yīng)該走向何處,對狀態(tài)數(shù)據(jù)的更改可以重定向
      執(zhí)行的目標(biāo)。采用狀態(tài)變遷控制模型的系統(tǒng)(更常見的是子系統(tǒng))一般以狀態(tài)機(jī)(state machine)的形式進(jìn)行建模和構(gòu)造。
      狀態(tài)機(jī)(state machine)有一組有窮的狀態(tài)和從一種狀態(tài)變到另一種狀態(tài)時(shí)執(zhí)行處理和變遷的規(guī)則來定義。兩種特殊情況,初始狀態(tài)(initial state)和最終狀態(tài)(final state),
      分別規(guī)定狀態(tài)機(jī)的起始點(diǎn)和結(jié)束條件。 狀態(tài)機(jī)的實(shí)現(xiàn)一般是一個(gè)switch語句的循環(huán),switch語句的分支對應(yīng)狀態(tài)機(jī)的狀態(tài);每個(gè)case語句執(zhí)行特定狀態(tài)的處理工作、
      更改狀態(tài)、并將控制權(quán)返回到狀態(tài)機(jī)的頂端。
      狀態(tài)機(jī)一般用來實(shí)現(xiàn)簡單的反應(yīng)系統(tǒng)(simple reactive system)(用戶界面、恒溫器和電動機(jī)控制、以及處理自動化應(yīng)用程序)、虛擬機(jī)、解釋器、正則表達(dá)式模式匹配器和詞法分析器。
      200.狀態(tài)變遷圖常常有助于理清狀態(tài)機(jī)的動作.
      
      9.3 元素封裝
       9.3.1 模塊
      201.在處理大量的代碼時(shí), 了解將代碼分解成單獨(dú)單元的機(jī)制極為重要.
      202.大多數(shù)情況下, 模塊的物理邊界是單個(gè)文件、組織到一個(gè)目錄中的多個(gè)文件或擁有統(tǒng)一前綴的文件的集合.
      9.3.2 命名空間
       模塊的一個(gè)重要思想就是信息隱藏(information hiding)的原則,它規(guī)定與模塊相關(guān)的所有信息都應(yīng)該為私有,除非它被特別聲明為公開。
      9.3.3 對象
      203.C中的模塊, 由提供模塊公開接口的頭文件和提供對應(yīng)實(shí)現(xiàn)的源文件組成.
      204.對象的構(gòu)造函數(shù)經(jīng)常用來分配與對象相關(guān)的資源, 并初始化對象的狀態(tài). 函數(shù)一般用來釋放對象在生命期中占用的資源.
      205.對象方法經(jīng)常使用類字段來存儲控制所有方法運(yùn)作的數(shù)據(jù)(比如查找表或字典)或維護(hù)類運(yùn)作的狀態(tài)信息(例如, 賦給每個(gè)對象一個(gè)標(biāo)識符的計(jì)數(shù)器).
      206.在設(shè)計(jì)良好的類中, 所有的字段都應(yīng)在聲明為private, 并用公開的訪問方法提供對它們的訪問.
      207.在遇到friend聲明時(shí), 要停下來分析一下, 看看繞過類封裝在設(shè)計(jì)上的理由.
      208.可以有節(jié)制地用運(yùn)算符增強(qiáng)特定類的可用性, 但用運(yùn)算符重載, 將類實(shí)現(xiàn)為擁有內(nèi)建算術(shù)類型相關(guān)的全部功能的類實(shí)體, 是不恰當(dāng)?shù)?
      9.3.4 泛型實(shí)現(xiàn)(generic implementation)
       數(shù)據(jù)結(jié)構(gòu)或算法的泛型實(shí)現(xiàn)(generic implementation) 的設(shè)計(jì)目的是能夠在任意數(shù)據(jù)類型上工作。
      209.泛型實(shí)現(xiàn)不是在編譯期間通過宏替換或語言所支持的功能(比如C++模板和Ada的泛型包)來實(shí)現(xiàn), 就是在運(yùn)行期間通過使用數(shù)據(jù)元素的指針和函數(shù)的指針、或?qū)ο蟮亩鄳B(tài)性實(shí)現(xiàn).
      編寫特定概念的泛型實(shí)現(xiàn)需要切實(shí)的智力勞動。因此,泛型實(shí)現(xiàn)最常用在,通過對實(shí)現(xiàn)的廣泛應(yīng)用能夠獲得相當(dāng)好處的情況下。
      
      典型的應(yīng)用包括(1)容器(經(jīng)常作為抽象數(shù)據(jù)類型來實(shí)現(xiàn)) (2)相關(guān)的算法,比如查找、排序和其他作用在集合和有序區(qū)間上的操作 (3)泛型數(shù)值算法
      
      
      9.3.5 抽象數(shù)據(jù)類型(Abstract data type, ADT)
      
      210.抽象數(shù)據(jù)類型經(jīng)常用來封裝常用的數(shù)據(jù)組織方案(比如樹|列表或棧), 或者對用戶隱藏?cái)?shù)據(jù)類型的實(shí)現(xiàn)細(xì)節(jié).
      9.3.6 庫
      211.使用庫的目的多種多樣: 重用源代碼或目標(biāo)代碼, 組織模塊集合, 組織和優(yōu)化編譯過程, 或是用來實(shí)現(xiàn)應(yīng)用程序各種特性的按需載入.
      9.3.7 進(jìn)程和過濾器
      212.大型的、分布式的系統(tǒng)經(jīng)常實(shí)現(xiàn)為許多互相協(xié)作的進(jìn)程.
      9.3.8 組件(component)
      9.3.9 數(shù)據(jù)存儲庫
      213.對于基于文本的數(shù)據(jù)儲存庫, 可以通過瀏覽存儲在其中的數(shù)據(jù), 破譯出它的結(jié)構(gòu).
      214.可以通過查詢數(shù)據(jù)字典中的表, 或使用數(shù)據(jù)庫專有的SQL命令, 比如show table, 來分析關(guān)系型數(shù)據(jù)庫的模式.
      9.4 構(gòu)架重用
       框架(Framework)和代碼向?qū)?code wizard)是代碼級構(gòu)架重用中的兩種機(jī)制。
      9.4.1 框架
      215.識別出重用的構(gòu)架元素后, 可以查找其最初的描述, 了解正確地使用這種構(gòu)架的方式, 以及可能出現(xiàn)的誤用.
      216.要詳細(xì)分析建立在某種框架之上的應(yīng)用程序, 行動的最佳路線就是從研究框架自身開始.
      9.4.2 代碼向?qū)В╟ode wizard)
      217.在閱讀向?qū)傻拇a時(shí), 不要期望太高, 否則您會感到失望.
      9.4.3 設(shè)計(jì)模式(design pattern)
      217.在閱讀向?qū)傻拇a時(shí), 不要期望太高, 否則您會感到失望.
      218.學(xué)習(xí)幾個(gè)基本的設(shè)計(jì)模式之后, 您會發(fā)現(xiàn), 您查看代碼構(gòu)架的方式會發(fā)生改變: 您的視野和詞匯將會擴(kuò)展到能夠識別和描述許多通用的形式.
      219.頻繁使用的一些模式, 但并不顯式地指出它們的名稱, 這是由于構(gòu)架性設(shè)計(jì)的重用經(jīng)常先于模式的形成.
      220.請?jiān)囍凑盏讓幽J絹砝斫鈽?gòu)架, 即使代碼中并沒有明確地提及模式.
      9.4.4 領(lǐng)域?qū)S械臉?gòu)架
       編譯器(處理某種計(jì)算機(jī)語言的應(yīng)用程序):一般都將任務(wù)劃分成,將字符組織成標(biāo)記(token的過程)--(lexical analysis,詞法分析),以及將標(biāo)記匯編成更大結(jié)構(gòu)的過程--(parsing,語法分析)。編譯器一般遵循,用不同的源代碼語義分析進(jìn)行詞法分析和語法分析、優(yōu)化和代碼生成等步驟;大多數(shù)解釋器將語法分析后的代碼轉(zhuǎn)換成內(nèi)部分析樹或字節(jié)碼表示,之后用狀態(tài)機(jī)或虛擬機(jī)對程序進(jìn)行處理。
       解釋器:sed(stream editor,流編輯器)命令解釋器圍繞一個(gè)循環(huán)構(gòu)建,該循環(huán)不斷讀取指令碼,并按指令的內(nèi)容執(zhí)行相應(yīng)的動作。分析后的程序在內(nèi)部存儲為一個(gè)鏈表,其中每個(gè)元素包含一個(gè)指令碼和相關(guān)的參數(shù)。變量cp是解釋器狀態(tài)(program state).
      221.大多數(shù)解釋器都遵循類似的處理構(gòu)架, 圍繞一個(gè)狀態(tài)機(jī)進(jìn)行構(gòu)建, 狀態(tài)機(jī)的操作依賴于解釋器的當(dāng)前狀態(tài)、程序指令和程序狀態(tài).
       參考架構(gòu)(reference archtecture):
      222.多數(shù)情況下, 參考構(gòu)架只是為應(yīng)用程序域指定一種概念性的結(jié)構(gòu), 具體的實(shí)現(xiàn)并非必須遵照這種結(jié)構(gòu).
      9.5 進(jìn)階讀物
      
      第四章 代碼閱讀工具 (原書:第十章: 代碼閱讀工具)
      
      223.詞匯工具可以高效地在一個(gè)大代碼文件中或者跨多個(gè)文件查找某種模式.
      
      224.使用程序編輯器和正則表達(dá)式查找命令, 瀏覽龐大的源代碼文件.
      
      225.以只讀方式瀏覽源代碼文件.
      
      226.使用正則表達(dá)式 ^function name 可以找出函數(shù)的定義.
      
      227.使用正則表達(dá)式的字符類, 可以查找名稱遵循特定模式的變量.
      
      228.使用正則表達(dá)式的否定字符類, 可以避免非積極匹配.
      
      229.使用正則表達(dá)式 symbol-1. *symbol-2, 可以查找出現(xiàn)在同一行的符號.
      
      230.使用編輯器的 tags 功能, 可以快速地找出實(shí)體的定義.
      
      231.可以用特定的 tag 創(chuàng)建工具, 增加編輯器的瀏覽功能.
      
      232.使用編輯器的大綱視圖, 可以獲得源代碼結(jié)構(gòu)的鳥瞰圖.
      
      233.使用您的編輯器來檢測源代碼中圓括號|方括號和花括號的匹配.
      
      234.使用 grep 跨多個(gè)文件查找代碼模式.
      
      235.使用 grep 定位符號的聲明|定義和應(yīng)用.
      
      236.當(dāng)您不能精確地表述要查找的內(nèi)容時(shí), 請使用關(guān)鍵單詞的詞干對程序的源代碼進(jìn)行查找.
      
      237.用 grep 過濾其他工具生成的輸出, 分離出您要查找的項(xiàng).
      
      238.將 grep 的輸出輸送到其他工具, 使復(fù)雜處理任務(wù)自動化.
      
      239.通過對 grep 的輸出進(jìn)行流編輯, 重用代碼查找的結(jié)果.
      
      240.通過選取與噪音模式不匹配的輸出行(grep-v), 過濾虛假的 grep 輸出.
      
      241.使用 fgrep 在源代碼中查找字符串列表.
      
      242.查找注釋, 或標(biāo)識符大小寫不敏感的語言編寫的代碼時(shí), 要使用大小寫不敏感的模式匹配(grep -i).
      
      243.使用 grep –n 命令行開關(guān), 可以創(chuàng)建與給定正則表達(dá)式匹配的文件和行號的檢查表.
      
      244.可以使用 diff 比較文件或程序不同版本之間的差別.
      
      245.在運(yùn)行 diff 命令時(shí), 可以使用 diff –b, 使文件比較算法忽略結(jié)尾的空格, 用 –w 忽略所有空白區(qū)域的差異, 用 –i 使文件比較對大小寫不敏感.
      
      246.不要對創(chuàng)建自己的代碼閱讀工具心存畏懼.
      
      247.在構(gòu)建自己的代碼閱讀工具時(shí): 要充分利用現(xiàn)代快速原型語言所提供的能力; 從簡單開始, 根據(jù)需要逐漸改進(jìn); 使用利用代碼詞匯結(jié)構(gòu)的各種試探法; 要允許一些輸出噪音或寂靜(無關(guān)輸出或缺失輸出); 使用其他工具對輸入進(jìn)行預(yù)處理, 或者對輸出進(jìn)行后期處理.
      
      248.要使編譯器成為您的: 指定恰當(dāng)級別的編譯器警告, 并小心地評估生成的結(jié)果.
      
      249.使用C預(yù)處理器理清那些濫用預(yù)處理器特性的程序.
      
      250.要徹底地了解編譯器如何處理特定的代碼塊, 需要查看生成的符號(匯編)代碼.
      
      251.通過分析相應(yīng)目標(biāo)文件中的符號, 可以清晰地了解源文件的輸入和輸出.
      
      252.使用源代碼瀏覽器瀏覽大型的代碼集合以及對象類型.
      
      253.要抵制住按照您的編碼規(guī)范對外部代碼進(jìn)行美化的誘惑; 不必要的編排更改會創(chuàng)建不同的代碼, 并妨礙工作的組織.
      
      254.優(yōu)美打印程序和編輯器語法著色可以使得程序的源代碼為易讀.
      
      255.cdecl 程序可以將難以理解的C和C++類型聲明轉(zhuǎn)換成純英語(反之亦然).
      
      256.實(shí)際運(yùn)行程序, 往往可以更深刻地理解程序的動作.
      
      257.系統(tǒng)調(diào)用|事件和數(shù)據(jù)包跟蹤程序可以增進(jìn)對程序動作的理解.
      
      258.執(zhí)行剖析器可以找出需要著重優(yōu)化的代碼, 驗(yàn)證輸入數(shù)據(jù)的覆蓋性, 以及分析算法的動作.
      
      259.通過檢查從未執(zhí)行的代碼行, 可以找出測試覆蓋的弱點(diǎn), 并據(jù)此修正測試數(shù)據(jù).
      
      260.要探究程序動態(tài)動作時(shí)的每個(gè)細(xì)節(jié), 需要在調(diào)試器中運(yùn)作它.
      
      261.將您覺得難以理解的代碼打印到紙上.
      
      262.可以繪制圖示來描繪代碼的動作.
      
      263.可以試著向別人介紹您在閱讀的代碼, 這樣做一般會增進(jìn)您對代碼的理解.
      
      264.理解復(fù)雜的算法或巧妙的數(shù)據(jù)結(jié)構(gòu), 要選擇一個(gè)安靜的環(huán)境, 然后聚精會神地考慮, 不要借助于任何計(jì)算機(jī)化或自動化的幫助.
      
       第五章 應(yīng)對大型項(xiàng)目 (第六章: 應(yīng)對大型項(xiàng)目)
      
      116.我們可以通過瀏覽項(xiàng)目的源代碼樹—包含項(xiàng)目源代碼的層次目錄結(jié)構(gòu), 來分析一個(gè)項(xiàng)目的組織方式. 源碼樹常常能夠反映出項(xiàng)目在構(gòu)架和軟件過程上的結(jié)構(gòu).
      
      117.應(yīng)用程序的源代碼樹經(jīng)常是該應(yīng)用程序的部署結(jié)構(gòu)的鏡像.
      
      118.不要被龐大的源代碼集合嚇倒; 它們一般比小型的專門項(xiàng)目組織得更出色.
      
      119.當(dāng)您首次接觸一個(gè)大型項(xiàng)目時(shí), 要花一些時(shí)間來熟悉項(xiàng)目的目錄樹結(jié)構(gòu).
      
      120.項(xiàng)目的源代碼遠(yuǎn)不只是編譯后可以獲得可執(zhí)行程序的計(jì)算機(jī)語言指令; 一個(gè)項(xiàng)目的源碼樹一般還包括規(guī)格說明|最終用戶和開發(fā)人員文檔|測試腳本|多媒體資源|編譯工具|例子|本地化文件|修訂歷史|安裝過程和許可信息.
      
      121.大型項(xiàng)目的編譯過程一般聲明性地借助依賴關(guān)系來說明. 依賴關(guān)系由工具程序, 如make/ant/Maven及其派生程序, 轉(zhuǎn)換成具體的編譯行動.
      
      122.大型項(xiàng)目中, 制作文件常常由配置步驟動態(tài)地生成; 在分析制作文件之前, 需要先執(zhí)行項(xiàng)目特定的配置.
      
      123.檢查大型編譯過程的各個(gè)步驟時(shí), 可以使用make程序的-n開關(guān)進(jìn)行預(yù)演.
      
      124.修訂控制系統(tǒng)提供從儲存庫中獲取源代碼最新版本的方式.
      
      125.可以使用相關(guān)的命令, 顯示可執(zhí)行文件中的修訂標(biāo)識關(guān)鍵字, 從而將可執(zhí)行文件與它的源代碼匹配起來.
      
      126.使用修訂日志中出現(xiàn)的bug跟蹤系統(tǒng)內(nèi)的編號, 可以在bug跟蹤系統(tǒng)的數(shù)據(jù)庫中找到有關(guān)的問題的說明.
      
      127.可以使用修訂控制系統(tǒng)的版本儲存庫, 找出特定的變更是如何實(shí)現(xiàn)的.
      
      128.定制編譯工具用在軟件開發(fā)過程的許多方面, 包括配置|編譯過程管理|代碼的生成|測試和文檔編制.
      
      129.程序的調(diào)試輸出可以幫助我們理解程序控制流程和數(shù)據(jù)元素的關(guān)鍵部分.
      
      130.跟蹤語句所在的地點(diǎn)一般也是算法運(yùn)行的重要部分.
      
      131.可以用斷言來檢驗(yàn)算法運(yùn)作的步驟|函數(shù)接收的參數(shù)|程序的控制流程|底層硬件的屬性和測試用例的結(jié)果.
      
      132.可以使用對算法進(jìn)行檢驗(yàn)的斷言來證實(shí)您對算法運(yùn)作的理解, 或?qū)⑺鳛橥评淼钠瘘c(diǎn).
      
      133.對函數(shù)參數(shù)和結(jié)果的斷言經(jīng)常記錄了函數(shù)的前置條件和后置條件.
      
      134.我們可以將測試整個(gè)函數(shù)的斷言作為每個(gè)給定函數(shù)的規(guī)格說明.
      
      135.測試用例可以部分地代替函數(shù)規(guī)格說明.
      
      136.可以使用測試用例的輸入數(shù)據(jù)對源代碼序列進(jìn)行預(yù)演.
      
       第六章 一個(gè)完整的例子 (第十一章: 一個(gè)完整的例子)
      
      265.模仿軟件的功能時(shí), 要依照相似實(shí)體的線路(類|函數(shù)|模塊). 在相似的現(xiàn)有實(shí)體中, 為簡化對源代碼庫的文本查找, 應(yīng)選取比較罕見的名稱.
      
      266.自動生成的文件常常會在文件的開關(guān)有一段注釋, 說明這種情況.
      
      267.如果試圖精確地分析代碼, 一般會陷入數(shù)量眾多的類|文件和模塊中, 這些內(nèi)容會很快將我們淹沒; 因此, 我們必須將需要理解的代碼限定在絕對必需的范圍之內(nèi).
      268.采用一種廣度優(yōu)先查找策略, 從多方攻克代碼閱讀中存在的問題, 進(jìn)到找出克服它們的方法為止.
      
       第七章基本編程元素 (第二章:基本編程元素)
      
      19.第一次分析一個(gè)程序時(shí), main是一個(gè)好的起始點(diǎn).
      
      20.層疊if-else if-...-else序列可以看作是由互斥選擇項(xiàng)組成的選擇結(jié)構(gòu).
      
      21.有時(shí), 要想了解程序在某一方面的功能, 運(yùn)行它可能比閱讀源代碼更為恰當(dāng).(運(yùn)行,并debug可以降低理解動態(tài)流程的難度)
      
      22.在分析重要的程序時(shí), 最好首先識別出重要的組成部分. (打蛇打三寸,抓住關(guān)鍵部分,可以快速理解)
      
      23.了解局部的命名約定, 利用它們來猜測變量和函數(shù)的功能用途.(類名用名詞或代詞或動名詞,最好不要用動詞,方法用動詞)
      
      24.當(dāng)基于猜測修改代碼時(shí), 您應(yīng)該設(shè)計(jì)能夠驗(yàn)證最初假設(shè)的過程. 這個(gè)過程可能包括用編譯器進(jìn)行檢查|引入斷言|或者執(zhí)行適當(dāng)?shù)臏y試用例.
      
      25.理解了代碼的某一部分, 可能幫助你理解余下的代碼.
      
      26.解決困難的代碼要從容易的部分入手.
      
      27.要養(yǎng)成遇到庫元素就去閱讀相關(guān)文檔的習(xí)慣; 這將會增強(qiáng)您閱讀和編寫代碼的能力.
      
      28.代碼閱讀有許多可選擇的策略: 自底向上和自頂向下的分析|應(yīng)用試探法和檢查注釋和外部文檔, 應(yīng)該依據(jù)問題的需要嘗試所有這些方法.
      
      29.for (i=0; i<n; i++)形式的循環(huán)執(zhí)行n次; 其他任何形式都要小心.
      
      30.涉及兩項(xiàng)不等測試(其中一項(xiàng)包括相等條件)的比較表達(dá)式('0' <= c && c <= '9')可以看作是區(qū)間成員測試(0 <= c <= 9).
      
      31.我們經(jīng)常可以將表達(dá)式應(yīng)用在樣本數(shù)據(jù)上, 借以了解它的含義. (用用例去驗(yàn)證表達(dá)式)
      
      32.使用De Morgan法則簡化復(fù)雜的邏輯表達(dá)式. (?)
      
      33.在閱讀邏輯乘表達(dá)式(&&)時(shí), 問題可以認(rèn)為正在分析的表達(dá)式以左的表達(dá)式均為true; 在閱讀邏輯和表達(dá)式(||)時(shí), 類似地, 可以認(rèn)為正在分析的表達(dá)式以左的表達(dá)式均為false.
      
      34.重新組織您控制的代碼, 使之更為易讀.
      
      35.將使用條件運(yùn)行符? :的表達(dá)式理解為if代碼.
      
      36.不需要為了效率, 犧牲代碼的易讀性.
      
      37.高效的算法和特殊的優(yōu)化確實(shí)有可能使得代碼更為復(fù)雜, 從而更難理解, 但這并不意味著使代碼更為緊湊和不易讀會提高它的效率.
      
      38.創(chuàng)造性的代碼布局可以用來提高代碼的易讀性.
      
      39.我們可以使用空格|臨時(shí)變量和括號提高表達(dá)式的易讀性.
      
      40.在閱讀您所控制的代碼時(shí), 要養(yǎng)成添加注釋的習(xí)慣. (在閱讀中比較復(fù)雜或難懂的地方要加注釋備注)
      
      41.我們可以用好的縮進(jìn)以及對變量名稱的明智選擇, 提高編寫欠佳的程序的易讀性.(養(yǎng)成好的編碼習(xí)慣)
      
      42.用diff程序分析程序的修訂歷史時(shí), 如果這段歷史跨越了整體重新縮排, 常??梢酝ㄟ^指定-w選項(xiàng), 讓diff忽略空白差異, 避免由于更改了進(jìn)層次而引入的噪音.(SVN/Git是否也有這個(gè)功能呢?)
      
      43.do循環(huán)的循環(huán)體至少執(zhí)行一次.
      
      44.執(zhí)行算術(shù)運(yùn)算時(shí), 當(dāng)b=2n-1時(shí), 可以將a&b理解為a%(b+1). (?)
      
      45.將a<<n理解為a*k, k=2n.
      
      46.將a>>n理解為a/k, k=2n.
      
      47.每次只分析一個(gè)控制結(jié)構(gòu), 將它的內(nèi)容看作是一個(gè)黑盒.
      
      48.將每個(gè)控制結(jié)構(gòu)的控制表達(dá)式看作是它所包含代碼的斷言.
      
      49.return, goto, break和continue語句, 還有異常, 都會影響結(jié)構(gòu)化的執(zhí)行流程. 由于這些語句一般都會終止或重新開始正在進(jìn)行的循環(huán),因此要單獨(dú)推理它們的行為.
      
      50.用復(fù)雜循環(huán)的變式和不變式, 對循環(huán)進(jìn)行推理.
      
      51.使用保持含義不變的變換重新安排代碼, 簡化代碼的推理工作.
      
       第八章 高級C數(shù)據(jù)類型 (第三章: 高級C數(shù)據(jù)類型)
      
      52.了解特定語言構(gòu)造所服務(wù)的功能之后, 就能夠更好地理解使用它們的代碼.
      
      53.識別并歸類使用指針的理由.
      
      54.在C程序中, 指針一般用來構(gòu)造鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)|動態(tài)分配的數(shù)據(jù)結(jié)構(gòu)|實(shí)現(xiàn)引用調(diào)用|訪問和迭代數(shù)據(jù)元素|傳遞數(shù)組參數(shù)|引用函數(shù)|作為其他值的別名|代表字符串|以及直接訪問系統(tǒng)內(nèi)存.
      
      55.以引用傳遞的參數(shù)可以用來返回函數(shù)的結(jié)果, 或者避免參數(shù)復(fù)制帶來的開銷.
      
      56.指向數(shù)組元素地址的指針, 可以訪問位于特定索引位置的元素.
      
      57.指向數(shù)組元素的指針和相應(yīng)的數(shù)組索引, 作用在二者上的運(yùn)算具有相同的語義.
      
      58.使用全局或static局部變量的函數(shù)大多數(shù)情況都不可重入(reentrant).
      
      59.字符指針不同于字符數(shù)組.
      
      60.識別和歸類應(yīng)用結(jié)構(gòu)或共用體的每種理由.
      
      61.C語言中的結(jié)構(gòu)將多個(gè)數(shù)據(jù)元素集合在一起, 使得它們可以作為一個(gè)整體來使用, 用來從函數(shù)中返回多個(gè)數(shù)據(jù)元素|構(gòu)造鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)|映射數(shù)據(jù)在硬件設(shè)備|網(wǎng)絡(luò)鏈接和存儲介質(zhì)上的組織方式|實(shí)現(xiàn)抽象數(shù)據(jù)類型|以及以面向?qū)ο蟮姆绞骄幊?
      
      62.共用體在C程序中主要用于優(yōu)化存儲空間的利用|實(shí)現(xiàn)多態(tài)|以及訪問數(shù)據(jù)不同的內(nèi)部表達(dá)方式.
      
      63.一個(gè)指針, 在初始化為指向N個(gè)元素的存儲空間之后, 就可以作為N個(gè)元素的數(shù)組來使用.
      
      64.動態(tài)分配的內(nèi)在塊可以電焊工地釋放, 或在程序結(jié)束時(shí)釋放, 或由垃圾回收器來完成回收; 在棧上分配的內(nèi)存塊當(dāng)分配它的函數(shù)退出后釋放.
      
      65.C程序使用typedef聲明促進(jìn)抽象, 并增強(qiáng)代碼的易讀性, 從而防范可移植性問題, 并模擬C++和Java的類聲明行為.
      
      66.可以將typedef聲明理解成變量定義: 變量的名稱就是類型的名稱; 變量的類型就是與該名稱對應(yīng)的類型.
      
       第九章 C數(shù)據(jù)結(jié)構(gòu) (第四章: C數(shù)據(jù)結(jié)構(gòu))
      
      67.根據(jù)底層的抽象數(shù)據(jù)類型理解顯式的數(shù)據(jù)結(jié)構(gòu)操作.
      
      68.C語言中, 一般使用內(nèi)建的數(shù)組類型實(shí)現(xiàn)向量, 不再對底層實(shí)現(xiàn)進(jìn)行抽象.
      
      69.N個(gè)元素的數(shù)組可以被序列for (i=0; i<N; i++)完全處理; 所有其他變體都應(yīng)該引起警惕.
      
      70.表達(dá)式sizeof(x)總會得到用memset或memcpy處理數(shù)組x(不是指針)所需的正確字節(jié)數(shù).
      
      71.區(qū)間一般用區(qū)間內(nèi)的第一個(gè)元素和區(qū)間后的第一個(gè)元素來表示.
      
      72.不對稱區(qū)間中元素的數(shù)目等于高位邊界與低位邊界的差.
      
      73.當(dāng)不對稱區(qū)間的高位邊界等于低位邊界時(shí), 區(qū)間為空.
      
      74.不對稱區(qū)間中的低位邊界代表區(qū)間的第一個(gè)元素; 高位邊界代表區(qū)間外的第一個(gè)元素.
      
      75.結(jié)構(gòu)的數(shù)組常常表示由記錄和字段組成的表.
      
      76.指向結(jié)構(gòu)的指針常常表示訪問底層記錄和字段的游標(biāo).
      
      77.動態(tài)分配的矩陣一般存儲為指向數(shù)組列的指針或指向元素指針的指針; 這兩種類型都可以按照二維數(shù)組進(jìn)行訪問.
      
      78.以數(shù)組形式存儲的動態(tài)分配矩陣, 用自定義訪問函數(shù)定位它們的元素.
      
      79.抽象數(shù)據(jù)類型為底層實(shí)現(xiàn)元素的使用(或誤用)方式提供一種信心的量度.
      
      80.數(shù)組用從0開始的順序整數(shù)為鍵, 組織查找表.
      
      81.數(shù)組經(jīng)常用來對控制結(jié)構(gòu)進(jìn)行高效編碼, 簡化程序的邏輯.
      
      82.通過在數(shù)組中每個(gè)位置存儲一個(gè)數(shù)據(jù)元素和一個(gè)函數(shù)指針(指向處理數(shù)據(jù)元素的函數(shù)), 可以將代碼與數(shù)據(jù)關(guān)聯(lián)起來.
      
      83.數(shù)組可以通過存儲供程序內(nèi)的抽象機(jī)(abstract machine)或虛擬機(jī)(virtual machine)使用的數(shù)據(jù)或代碼, 控制程序的運(yùn)作.
      
      84.可以將表達(dá)式sizeof(x) / sizeof(x[0])理解為數(shù)組x中元素的個(gè)數(shù).
      
      85.如果結(jié)構(gòu)中含有指向結(jié)構(gòu)自身|名為next的元素, 一般說來, 該結(jié)構(gòu)定義的是單向鏈表的結(jié)點(diǎn).
      
      86.指向鏈表結(jié)點(diǎn)的持久性(如全局|靜態(tài)或在堆上分配)指針常常表示鏈表的頭部.
      
      87.包含指向自身的next和prev指針的結(jié)構(gòu)可能是雙向鏈表的結(jié)點(diǎn).
      
      88.理解復(fù)雜數(shù)據(jù)結(jié)構(gòu)的指針操作可以將數(shù)據(jù)元素畫為方框|指針畫為箭頭.
      
      89.遞歸數(shù)據(jù)結(jié)構(gòu)經(jīng)常用遞歸算法來處理.
      
      90.重要的數(shù)據(jù)結(jié)構(gòu)操作算法一般用函數(shù)參數(shù)或模板參數(shù)來參數(shù)化.
      
      91.圖的結(jié)點(diǎn)常常順序地存儲在數(shù)組中, 鏈接到鏈表中, 或通過圖的邊鏈接起來.
      
      92.圖中的邊一般不是隱式地通過指針, 就是顯式地作為獨(dú)立的結(jié)構(gòu)來表示.
      
      93.圖的邊經(jīng)常存儲為動態(tài)分配的數(shù)組或鏈表, 在這兩種情況下, 邊都錨定在圖的結(jié)點(diǎn)上.
      
      94.在無向圖中, 表達(dá)數(shù)據(jù)時(shí)應(yīng)該將所有的結(jié)點(diǎn)看作是等同的, 類似地, 進(jìn)行處理任務(wù)的代碼也不應(yīng)該基于它們的方向來區(qū)分邊.
      
      95.在非連通圖中, 執(zhí)行遍歷代碼應(yīng)該能夠接通孤立的子圖.
      
      96.處理包含回路的圖時(shí), 遍歷代碼應(yīng)該避免在處理圖的回路進(jìn)入循環(huán).
      
      97.復(fù)雜的圖結(jié)構(gòu)中, 可能隱藏著其他類型的獨(dú)立結(jié)構(gòu).
      
       第十章 高級控制流程 (第五章: 高級控制流程)
      
      98.采用遞歸定義的算法和數(shù)據(jù)結(jié)構(gòu)經(jīng)常用遞歸的函數(shù)定義來實(shí)現(xiàn).
      
      99.推理遞歸函數(shù)時(shí), 要從基準(zhǔn)落伍測試開始, 并認(rèn)證每次遞歸調(diào)用如何逐漸接近非遞歸基準(zhǔn)范例代碼.
      
      100.簡單的語言常常使用一系列遵循該語言語法結(jié)構(gòu)的函數(shù)進(jìn)行語法分析.
      
      101.推理互遞歸函數(shù)時(shí), 要基于底層概念的遞歸定義.
      
      102.尾遞歸調(diào)用等同于一個(gè)回到函數(shù)開始處的循環(huán).
      
      103.將throws子句從方法的定義中移除, 然后運(yùn)行Java編譯器對類的源代碼進(jìn)行編譯, 就可以容易地找到那些可能隱式地生成異常的方法.
      
      104.在多處理器計(jì)算機(jī)上運(yùn)行的代碼常常圍繞進(jìn)程或線程進(jìn)行組織.
      
      105.工作群并行模型用于在多個(gè)處理器間分配工作, 或者創(chuàng)建一個(gè)任務(wù)池, 然后將大量需要處理標(biāo)準(zhǔn)化的工作進(jìn)行分配.
      
      106.基于線程的管理者/工人并行模型一般將耗時(shí)的或阻塞的操作分配給工人子任務(wù), 從而維護(hù)中心任務(wù)的響應(yīng)性.
      
      107.基于進(jìn)程的管理者/工人并行模型一般用來重用現(xiàn)有的程序, 或用定義良好的接口組織和分離粗粒度的系統(tǒng)模塊.
      
      108.基于流水線的并行處理中, 每個(gè)任務(wù)都接收到一些輸入, 對它們進(jìn)行一些處理, 并將生成的輸出傳遞給下一個(gè)任務(wù), 進(jìn)行不同的處理.
      
      109.競爭條件很難捉摸, 相關(guān)的代碼常常會將競爭條件擴(kuò)散到多個(gè)函數(shù)或模塊; 因而, 很難隔離由于競爭條件導(dǎo)致的問題.
      
      110.對于出現(xiàn)在信號處理器中的數(shù)據(jù)結(jié)構(gòu)操作代碼和庫調(diào)用要保持高度警惕.
      
      111.在閱讀包含宏的代碼時(shí), 要注意, 宏既非函數(shù), 也非語句.
      
      112.do…while(0)塊中的宏等同于控制塊中的語句.
      
      113.宏可以訪問在它的使用點(diǎn)可見的所有局部變量.
      
      114.宏調(diào)用可改變參數(shù)的值
      
      115.基于宏的標(biāo)記拼接能夠創(chuàng)建新的標(biāo)記符.
      
       第十一章 編碼規(guī)范和約定 (第七章: 編碼規(guī)范和約定)
      
      137.了解了給定代碼庫所遵循的文件組織方式后, 就能更有效率地瀏覽它的源代碼.
      
      138.閱讀代碼時(shí), 首先要確保您的編輯器或優(yōu)美打印程序的tab設(shè)置, 與代碼遵循的風(fēng)格規(guī)范一致.
      
      139.可以使用代碼塊的縮進(jìn), 快速地掌握代碼的總體結(jié)構(gòu).
      
      140.對編排不一致的代碼, 應(yīng)該立即給予足夠的警惕.
      
      141.分析代碼時(shí), 對標(biāo)記為XXX, FIXME和TODO的代碼序列要格外注意: 錯(cuò)誤可能就潛伏在其中.
      
      142.常量使用大寫字母命名, 單詞用下劃線分隔.
      
      143.在遵循Java編碼規(guī)范的程序中, 包名(package name)總是從一個(gè)頂級的域名開始(例如, org, com), 類名和接口名由大寫字母開始, 方法
      
      和變量名由小寫字母開始.
      
      144.用戶界面控件名稱之前的匈牙利記法的前綴類型標(biāo)記可以幫助我們確定它的作用.
      
      145.不同的編程規(guī)范對可移植構(gòu)造的構(gòu)成有不同的主張.
      
      146.在審查代碼的可移植性, 或以某種給定的編碼規(guī)范作為指南時(shí), 要注意了解規(guī)范對可移植性需求的界定與限制.
      
      147.如果GUI功能都使用相應(yīng)的編程結(jié)構(gòu)來實(shí)現(xiàn), 則通過代碼審查可以輕易地驗(yàn)證給定用戶界面的規(guī)格說明是否被正確地采用.
      
      148.了解項(xiàng)目編譯過程的組織方式與自動化方式之后, 我們就能夠快速地閱讀與理解對應(yīng)的編譯規(guī)則.
      
      149.當(dāng)檢查系統(tǒng)的發(fā)布過程時(shí), 常??梢詫⑾鄳?yīng)發(fā)行格式的需求作為基準(zhǔn).
      
      附錄A 代碼概況
      C類:
      [] netbsd 原始文件:NetBSD 1.5_ALPHA 當(dāng)前流行度:流行 http://os.chinaunix.net/a2005/0618/965/000000965265.shtml
      [] XFree86-3.3 原始文件:netBSD 1.5_ALPHA FreeBSD 當(dāng)前流行度:流行
       SendMail
       named域名服務(wù)器
       tcpdump
      [] apache 原始文件:apache_1.3.22 當(dāng)前流行度:流行
      [] perl 原始文件:perl-5.6.1 當(dāng)前流行度:流行
      C++類:
      [] vcf Visual Component Framework http://www.codeproject.com/Articles/792/Visual-Component-Framework
      [] ACE 原始文件:ACE-5.2+TAO-1.2.zip 當(dāng)前流行度:流行 ACE:http://www.cs.wustl.edu/~schmidt/ACE.html
      [] socket socket++-1.11
      [] qtchat
      [] demoGL demoGL
      [] OpenCL OpenCL
      [] purenum purenum
      Java類:
      [] jt4 jakarta-tomcat-4.0
      [] argouml
      [] hsqldb
      [] cocoon
  •     個(gè)人覺得這本書是講授代碼閱讀的經(jīng)典之作,很多牛人都推薦閱讀的。之前常聽網(wǎng)絡(luò)上的蔡學(xué)鏞大牛說,程序員提高的兩個(gè)途徑,一個(gè)是寫代碼,一個(gè)就是閱讀代碼了。所以推薦想成為高手的非高手,以及想持續(xù)成為高手的朋友都讀下這本書
  •     技術(shù)類的書籍真是什么樣的都有,教你怎么閱讀代碼,看是沒有必要,誰不會閱讀代碼?打開文本編輯器,從上而下,至左到右,而且好一點(diǎn)的編輯器都支持語法加亮,收縮等,如果覺得不夠,還可以在IDE里邊閱讀。但是讀完這本書,應(yīng)該會知道閱讀代碼也是很講究的,不是那么簡單的。
  •     
      
      
      
      和我想象中不太一樣,隨書光盤帶了很多開源代碼的例子,不過本書不是萊昂氏那樣條分縷析,而是指點(diǎn)閱讀的方法,鋪得很開以致感覺有些瑣碎,有些內(nèi)容在別的書里講的更深入。
      
      個(gè)人最喜歡后面幾章和附錄。
  •     首先,閱讀代碼這個(gè)領(lǐng)域確實(shí)很少有書涉及到,作者試圖闡述他閱讀代碼的一些經(jīng)驗(yàn),當(dāng)然,這很值得我們參考,尤其是閱讀開源代碼的人,可能會從中學(xué)到很多開源項(xiàng)目的規(guī)范與設(shè)計(jì)方法,從而更好地去理解open source
      另外,我覺得這本書最重要的地方在于,一,它論述了閱讀代碼的重要性,我們程序員常常太醉心于寫代碼,卻忘了開源世界寶貴的源碼資源,如同作家通常從其他作品中汲取營養(yǎng)一樣,一個(gè)好的程序員也必然要從其他優(yōu)秀的代碼中學(xué)習(xí)編碼技巧及經(jīng)驗(yàn);二,它試圖從閱讀代碼的角度來闡述如何寫一個(gè)程序,這個(gè)視角很新穎,雖然前面幾章對于有經(jīng)驗(yàn)的程序員來說顯得有些冗余
      對于那些希望從書中學(xué)到更多閱讀代碼技巧的人,可能會有些失望.因?yàn)榭赐赀@本書,你面對一個(gè)大系統(tǒng),可能依然無從下手.
      我給這本書四星,因?yàn)檫@本書很不錯(cuò),但還不夠好
  •     不是C的普及讀本,
      
      而是從代碼方面進(jìn)行黑客文化的回憶,
      
      通過代碼閱讀方法,可以體驗(yàn)到幾十年積累下來的文化規(guī)約^^^^
      
      
      
  •     亞馬遜上這本書的評價(jià)是四顆星,所以一開始還有些期待,盡管剛看了目錄就覺得它不是很誘人。
      后來發(fā)現(xiàn)亞馬遜上即使給它打四五顆星的,還是說了它不少不足。
      耐著性子用一個(gè)小時(shí)翻完這本書,發(fā)現(xiàn)亞馬遜上指出的不足都非常中肯,比如沒有重點(diǎn)、凌亂、只適合初學(xué)者等等。
      這本書中有太多莫名其妙的東西,根本就只應(yīng)該出現(xiàn)在C語言基礎(chǔ)教程中。與我的預(yù)期相差太遠(yuǎn)。
      倒是覺得,每一章節(jié)末尾的“進(jìn)階閱讀”列表很不錯(cuò),它差不多說明了你要閱讀開源程序所需要具備的知識與能力,是一個(gè)頗詳細(xì)的reading list。
  •   真失望,我是來找方法的。。
  •   補(bǔ)充:
    又仔細(xì)看了進(jìn)階閱讀列表,發(fā)現(xiàn)寫書的這個(gè)希臘人還真是個(gè)老學(xué)究式的人物呢。Dijkstra 68年寫的關(guān)于goto語句的文章都能被他翻出來列上。
    平心而論,這本書一定包含了他幾十年的讀書筆記,不簡單呢??墒蔷褪遣缓每?。
  •   哈哈,只有一笑,無語……
  •   我覺得代碼閱讀因代碼而異

推薦圖書


 

250萬本中文圖書簡介、評論、評分,PDF格式免費(fèi)下載。 第一圖書網(wǎng) 手機(jī)版

京ICP備13047387號-7