如何閱讀他人的程序代碼(上)——技巧學(xué)習(xí)篇

一、讀懂程序代碼旷偿,使心法皆為我所用?

程序代碼是別人寫的烹俗,只有原作者才真的了解程序代碼的用途及涵義。許多程序人心里都有一種不自覺的恐懼感萍程,深怕被迫去碰觸其他人所寫的程序代碼幢妄。但是,與其抗拒接收別人的程序代碼茫负,不如徹底了解相關(guān)的語言和慣例蕉鸳,當(dāng)成是培養(yǎng)自我實(shí)力的基石。?

對大多數(shù)的程序人來說朽褪,撰寫程序代碼或許是令人開心的一件事情置吓,但我相信,有更多人視閱讀他人所寫成的程序代碼為畏途缔赠。許多人寧可自己重新寫過一遍程序代碼衍锚,也不愿意接收別人的程序代碼,進(jìn)而修正錯(cuò)誤嗤堰、維護(hù)它們戴质、甚至加強(qiáng)功能。?

這其中的關(guān)鍵究竟在何處呢踢匣?若是一語道破告匠,其實(shí)也很簡單,程序代碼是別人寫的离唬,只有原作者才真的了解程序代碼的用途及涵義后专。許多程序人心里都有一種不自覺的恐懼感,深怕被迫去碰觸其他人所寫的程序代碼输莺。這是來自于人類內(nèi)心深處對于陌生事物的原始恐懼戚哎。?

讀懂別人寫的程序代碼裸诽,讓你收獲滿滿?

不 過,基于許多現(xiàn)實(shí)的原因型凳,程序人時(shí)常受迫要去接收別人的程序代碼丈冬。例如,同事離職了甘畅,必須接手他遺留下來的工作埂蕊;也有可能你是剛進(jìn)部門的菜鳥,而同事經(jīng)驗(yàn) 值夠了疏唾、升級(jí)了蓄氧,風(fēng)水輪流轉(zhuǎn),一代菜鳥換菜鳥荸实。甚至匀们,你的公司所承接的項(xiàng)目,必須接手或是整合客戶前一個(gè)廠商所遺留下來的系統(tǒng)准给,你們手上只有那套系統(tǒng)的原 始碼(運(yùn)氣好時(shí),還有數(shù)量不等的文件)重抖。?

諸如此類的故事露氮,其實(shí)時(shí)常在程序人身邊或身上持續(xù)上演著。許多程序人都將接手他人的程序代碼钟沛,當(dāng)做一件悲慘的事情畔规。每個(gè)人都不想接手別人所撰寫的程序代碼,因?yàn)椴幌牖〞r(shí)間去探索恨统,寧可將生產(chǎn)力花在產(chǎn)生新的程序代碼叁扫,而不是耗費(fèi)在了解這些程序代碼上。?

很 遺憾的是畜埋,上述的情況對程序人來說很難避免莫绣。我們總是必須碰觸到其他人所寫成的程序代碼,甚至必須了解它悠鞍、加以修改对室。對于這項(xiàng)需求,在現(xiàn)今開放原始碼的風(fēng) 氣如此盛行的今日咖祭,正如之前的「程序設(shè)計(jì)2.0」文中所提到的掩宜,你可以透過開放原始碼學(xué)習(xí)到新的技術(shù)、學(xué)習(xí)到高手的架構(gòu)設(shè)計(jì)么翰,大幅提高學(xué)習(xí)的效率及效果牺汤。 你甚至可以直接自開放原始碼項(xiàng)目中抽取、提煉出自己所需的程序代碼浩嫌,站在巨人的肩膀上檐迟,直接由彼端獲得所需的生產(chǎn)力戴已。從這個(gè)觀點(diǎn)來看,讀懂別人所寫的程序 代碼锅减,就不再只是從負(fù)面觀點(diǎn)的「被迫接收」糖儡,而是極具正面價(jià)值的「汲取養(yǎng)份」。?

先了解系統(tǒng)架構(gòu)與行為模式怔匣,再細(xì)讀?

倘若撰寫程序代碼是程序人的重要技藝之一握联,那么讀懂別人的程序代碼、接著加以修改每瞒,也勢必是另一個(gè)重要的技藝金闽。?

如果你不能熟悉這項(xiàng)工作,不僅在遭逢你所不愿面對的局面時(shí)剿骨,無法解決眼前接手他人程序代碼的難題代芜,更重要的是,當(dāng)你看著眼前現(xiàn)成的程序代碼浓利,卻不知如何從中擷取自己所需挤庇,導(dǎo)致最后只能入寶山空手回,望之興嘆贷掖。?

接觸他人的程序代碼嫡秕,大致上可以分為三種程度:一、了解苹威,二昆咽、修改、擴(kuò)充牙甫,三掷酗、抽取、提煉窟哺。?

了解別人的程序代碼是最基礎(chǔ)的工作泻轰,倘若不能了解自己要處理的程序代碼,就甭論修改或擴(kuò)充脏答,更不可能去蕪存菁糕殉,從中萃取出自己所需,回收再利用別人所撰寫的程序代碼殖告。?

雖說是「閱讀」阿蝶,但程序代碼并不像文章或小說一樣,透過這種做法黄绩,便能夠獲得一定程度的了解羡洁。閱讀文章或小說時(shí),幾乎都是循序地閱讀爽丹,你只消翻開第一頁筑煮,一行行閱讀下去即可辛蚊。但是,有許多程序人在試著閱讀其他人的程序代碼時(shí)真仲,卻往往有不知如何讀起的困難袋马。?

或許找到系統(tǒng)的第一頁(也就是程序代碼執(zhí)行的啟始點(diǎn))并不難,但是復(fù)雜度高的系統(tǒng)秸应,有時(shí)十分龐大虑凛,有時(shí)千頭萬緒。?

從 程序代碼的啟始點(diǎn)開始讀起软啼,一來要循序讀完所有的程序代碼曠日費(fèi)時(shí)桑谍,二來透過這種方式來了解系統(tǒng),很難在腦中構(gòu)建出系統(tǒng)的面貌祸挪,進(jìn)而了解到系統(tǒng)真正的行 為锣披。所以,閱讀程序代碼的重點(diǎn)贿条,不在于讀完每一行程序代碼雹仿,而是在于有效率地透過探索及閱讀,從而了解系統(tǒng)的架構(gòu)及行為模式闪唆。以便在你需要了解任何片段的 細(xì)節(jié)實(shí)作時(shí)盅粪,能夠很快在腦上對映到具體的程序代碼位置,直到那一刻悄蕾,才是細(xì)讀的時(shí)機(jī)。?


熟悉溝通語言與慣例用語?

不論如何础浮,有些基本的準(zhǔn)備帆调,是閱讀他人程序代碼時(shí)必須要有的。?

首先豆同,你最好得了解程序代碼寫成的程序語言番刊。想要讀懂法文寫成的小說,總不能連法文都不懂吧影锈。有些情況則很特殊芹务。我們雖然不懂該程序代碼撰寫所用的語言,但是因?yàn)楝F(xiàn)代語言的高階化鸭廷,而且流行的程序語言多半都是血統(tǒng)相近枣抱,所以即使不那么熟悉,有時(shí)也可勉力為之辆床。?

除了認(rèn)識(shí)所用語言之外佳晶,再來就是要先確認(rèn)程序代碼所用的命名慣例(naming convention)。了解命名慣例很重要讼载,不同的程序人或開發(fā)團(tuán)隊(duì)轿秧,差異可能很大中跌。?

這命名慣例涵蓋的范圍通常包括了變量的名稱、函式的名稱菇篡、類別(如果是面向?qū)ο蟮脑挘┑拿Q漩符、原始碼檔案、甚至是項(xiàng)目建構(gòu)目錄的名稱驱还。倘若使用了像設(shè)計(jì)模式之類的方法嗜暴,這些名稱更有一些具體的表述方式。?

命 名慣例有點(diǎn)像是程序人在程序語言之上铝侵,另行建構(gòu)的一組溝通行話灼伤。程序人會(huì)透過共通約束、遵守的命名慣例咪鲜,來表達(dá)一些較高階的概念狐赡。例如,有名的匈牙利式命 名法疟丙,便將變量名稱以屬性颖侄、型別、說明合并在一起描述享郊。對程序人來說览祖,這種方式能夠提供更豐富的信息,以了解該變量的作用及性質(zhì)炊琉。?

對 程序代碼閱讀來說展蒂,熟悉這個(gè)做法之所以重要,是因?yàn)楫?dāng)你了解整個(gè)系統(tǒng)所采用的慣例時(shí)苔咪,你便能試著以他們所共同操用的語匯來進(jìn)行理解锰悼。倘若,不能了解其所用 的慣例团赏,那么這些額外提供的信息箕般,就無法為你所用。像以設(shè)計(jì)模式寫成的程序代碼舔清,同樣處處充滿著模式的名稱丝里,諸如:Factory、Facade体谒、 Proxy等等杯聚。以這些名稱指涉的類別,也直接透過名稱营密,表達(dá)了它們自身的作用械媒。對于懂得這命名慣例的讀者來說,不需要深入探索,也能很快捕捉到這些類別 的意義纷捞。?

當(dāng)你拿到一套必須閱讀的程序代碼時(shí)痢虹,最好先取得命名慣例的說明文件。然而主儡,并不是每套程序代碼都附有此類的說明文件奖唯。另一個(gè)方式,就是自己到程序代碼中糜值,大略瀏覽一遍丰捷,有經(jīng)驗(yàn)的程序人可以輕易發(fā)掘出該系統(tǒng)所用的命名慣例。?

常見的命名方式不脫那幾類寂汇,這時(shí)候經(jīng)驗(yàn)就很重要病往,倘若你知道的慣例越多,就越能輕易識(shí)別他人所用的慣例骄瓣。如果運(yùn)氣很糟停巷,程序代碼所用的慣例是前所未見的,那么你也得花點(diǎn)時(shí)間歸納榕栏,憑自己的力量找出這程序代碼命名上的規(guī)則畔勤。?

掌握程序代碼撰寫者的心態(tài)與習(xí)慣?

大 多數(shù)的程序代碼,基本上都依循一致的命名慣例扒磁。不過運(yùn)氣更差的時(shí)候庆揪,一套系統(tǒng)中可能會(huì)充斥著多套命名慣例。這有可能是因?yàn)殚_發(fā)團(tuán)隊(duì)由多組人馬所構(gòu)成妨托,每組 人馬都有不同的文化缸榛,而在項(xiàng)目開發(fā)管理又沒有管控得宜所造成。最糟的情況兰伤,程序代碼完全沒有明顯的慣例可言仔掸,這時(shí)候閱讀的難度就更高了。?

想要閱讀程序代碼医清,得先試著體會(huì)程序代碼作者的「心」。想要這么做卖氨,就得多了解對方所使用的語言会烙,以及慣常運(yùn)用的語匯。在下一回中筒捺,我們將繼續(xù)探討閱讀程序代碼的相關(guān)議題柏腻。?


二、摸清架構(gòu)系吭,便可輕松掌握全貌?

在本文中五嫂,我們的重點(diǎn)放在:要了解一個(gè)系統(tǒng),最好是采取由上至下的方式。先試著捕捉系統(tǒng)架構(gòu)性的觀念沃缘,不要過早鉆進(jìn)細(xì)節(jié)躯枢,因?yàn)槟峭ǔτ谀懔私馊玻瑳]有多大的幫助槐臀。閱讀程序代碼不需要從第一行讀起锄蹂,我們的目的并不是在于讀遍每一段程序代碼。

基于許多原因水慨,程序人需要閱讀其他人所寫成的程序代碼得糜。而對程序設(shè)計(jì)2.0時(shí)代的程序人來說,最正面的價(jià)值在于晰洒,能讀懂別人程序的人朝抖,才有能力從中萃取自己所需的程序,藉以提高生產(chǎn)力谍珊。?

閱讀程序代碼的目的治宣,在于了解全貌而非細(xì)節(jié)?

想要讀懂別人程序代碼的根本基礎(chǔ),便是了解對方所用的程序語言及命名慣例抬驴。有了這個(gè)基礎(chǔ)之后炼七,才算是具備了基本的閱讀能力。正如我之前提到的──想要讀懂法文寫成的小說布持,總不能連法文都不懂吧豌拙。閱讀程序代碼和閱讀文學(xué)作品,都需要了解撰寫所用的語言及作者習(xí)用的語匯题暖。?

但我們在閱讀文學(xué)作品通常是采循序的方式按傅,也就是從第一頁開始,一行一行地讀下去胧卤,依循作者為你鋪陳的步調(diào)唯绍,逐漸進(jìn)到他為你準(zhǔn)備好的世界里。?

閱讀程序代碼卻大大不同枝誊。我們很少從第一行開始讀起况芒,因?yàn)槌撬呛芎唵蔚膯尉€程程序,否則很少這么做叶撒。因?yàn)橐沁@么做绝骚,就很難了解整個(gè)系統(tǒng)的全貌。?

是的祠够,我們這邊提到了一個(gè)重點(diǎn)压汪,閱讀程序代碼的目的在于了解系統(tǒng)的全貌,而不是在于只是為了地毯式的讀遍每一段程序代碼古瓤。?

就 拿面向?qū)ο蟪绦蛘Z言所寫成的系統(tǒng)來說止剖,整個(gè)系統(tǒng)被拆解腺阳、分析成為一個(gè)個(gè)獨(dú)立的類別。閱讀個(gè)別類別的程序代碼穿香,或許可以明白每項(xiàng)類別對象個(gè)別的行為亭引。但對于 各類別對象之間如何交互影響、如何協(xié)同工作扔水,又很容易陷入盲人摸象的困境痛侍。這是因?yàn)楦黝悇e的程序代碼,只描述個(gè)別對象的行為魔市,而片段的閱讀就只能造就片面 的認(rèn)識(shí)主届。?

由上而下厘清架構(gòu)后,便可輕易理解組成關(guān)系?

如果你想要跳脫困境待德,不 想浪費(fèi)大量時(shí)間閱讀程序代碼君丁,卻始終只能捕捉到對系統(tǒng)片段認(rèn)識(shí),就必須轉(zhuǎn)換到另一種觀點(diǎn)來看待系統(tǒng)将宪。從個(gè)別的類別行為著手绘闷,是由下至上(Bottom- Up)的方法;在閱讀程序代碼時(shí)较坛,卻應(yīng)該先采由上至下(Top-Down)的方式印蔗。對程序代碼的閱讀來說,由上至下意謂著丑勤,你得先了解整個(gè)系統(tǒng)架構(gòu)华嘹。?

系統(tǒng)的架構(gòu)是整個(gè)系統(tǒng)的骨干、支柱法竞。它表現(xiàn)出系統(tǒng)最突出的特征耙厚。知道系統(tǒng)架構(gòu)究竟屬于那一種類型,通常大大有益于了解系統(tǒng)的個(gè)別組成之間的靜態(tài)及動(dòng)態(tài)關(guān)系岔霸。?

有些系統(tǒng)因?yàn)樗玫募夹g(shù)或框架的關(guān)系薛躬,決定了最上層的架構(gòu)。例如呆细,采用Java Servlet/JSP技術(shù)的應(yīng)用系統(tǒng)型宝,最外層的架構(gòu)便是以J2EE(或起碼J2EE中的Web Container)為根本。?

使 用Java Servlet/JSP技術(shù)時(shí)絮爷,決定了某些組成之間的關(guān)系诡曙。例如,Web Container依據(jù)web.xml的內(nèi)容加載所有的Servlets略水、Listeners、以及Filters劝萤。每當(dāng)Context發(fā)生事件(例如初 始化)時(shí)渊涝,它便會(huì)通知Listener類別。每當(dāng)它收到來自客戶端的請求時(shí),便會(huì)依循設(shè)定的所有Filter Chain跨释,讓每個(gè)Filter都有機(jī)會(huì)檢查并處理此一請求胸私,最后再將請求導(dǎo)至用來處理該請求的Servlet。?

當(dāng)我們明白某個(gè) 系統(tǒng)采用這樣的架構(gòu)時(shí)鳖谈,便可以很容易地知道各個(gè)組成之間的關(guān)系岁疼。即使我們還不知道究竟有多少Servlets,但我們會(huì)知道缆娃,每當(dāng)收到一個(gè)請求時(shí)捷绒,總是會(huì) 有個(gè)相對應(yīng)的Servlet來處理它。當(dāng)想要關(guān)注某個(gè)請求如何處理時(shí)贯要,我應(yīng)該去找出這個(gè)請求對應(yīng)的Servlet暖侨。?


了解架構(gòu),必須要加上層次感?

同 樣的崇渗,以Java寫成的Web應(yīng)用程序中字逗,也許會(huì)應(yīng)用諸如Struts之類的MVC框架,以及像Hibernate這樣的數(shù)據(jù)存取框架宅广。它們都可以視為最 主要的架構(gòu)下的較次級(jí)架構(gòu)葫掉。而各個(gè)應(yīng)用系統(tǒng),甚至有可能在Struts及Hibernate之下跟狱,建立自有的更次級(jí)的架構(gòu)俭厚。?

也就 是說,當(dāng)我們談到「架構(gòu)」這樣的觀念時(shí)兽肤,必須要有層次感套腹。而不論是那一層級(jí)的架構(gòu),都會(huì)定義出各自的角色资铡,以及角色間的關(guān)系电禀。對閱讀者來說,相較于直接切 入最細(xì)微的單一角色行為笤休,不如了解某個(gè)特定的架構(gòu)中尖飞,究竟存在多少角色,以及這些角色之間的互動(dòng)模式店雅,比較能夠幫助我們了解整個(gè)系統(tǒng)的運(yùn)作方式政基。?

這 是一個(gè)很重要的關(guān)鍵,當(dāng)你試著進(jìn)到最細(xì)節(jié)處之前闹啦,應(yīng)該先試著找出參與的角色沮明,及他們之間的關(guān)系。例如窍奋,對事件驅(qū)動(dòng)式的架構(gòu)而言荐健,有3個(gè)很重要的角色酱畅。一個(gè) 是事件處理的分派器(Event Dispatcher)、一個(gè)是事件產(chǎn)生者(Event Generator)江场、另一個(gè)則是事件處理器(Event Handler)纺酸。?

事件產(chǎn)生器產(chǎn)生事件,并送至事件分派器址否,而事件分派器負(fù)責(zé)找出各事件相對應(yīng)的事件處理器餐蔬,并且轉(zhuǎn)交該事件,并命令事件處理器加以處理佑附。像Windows的GUI應(yīng)用程序樊诺,便是采用事件驅(qū)動(dòng)式的架構(gòu)。?

當(dāng)你知道此類的應(yīng)用程序皆為事件驅(qū)動(dòng)式的架構(gòu)時(shí)帮匾,你便可以進(jìn)一步得知啄骇,在這樣的架構(gòu)下會(huì)有3種主要的角色。雖然也許還不清楚整個(gè)系統(tǒng)中瘟斜,究竟會(huì)需要處理多少事件的類型缸夹,但對你而言,已經(jīng)建立了對系統(tǒng)全貌最概觀的認(rèn)識(shí)螺句。?

雖然你還不清楚所有的細(xì)節(jié)虽惭,但諸如確切會(huì)有那些事件類型之類的信息,在此刻還不重要──不要忘了蛇尚,我們采取的是由上而下的方式芽唇,要先摸清楚主建筑結(jié)構(gòu),至于壁紙的花色怎么處理取劫,那是到了尾聲時(shí)才會(huì)做的事匆笤。?

探索架構(gòu)的第一件事:找出系統(tǒng)如何初始化?

有經(jīng)驗(yàn)的程序人,對于時(shí)常被運(yùn)用的架構(gòu)都很熟悉谱邪。常常只需要瞧上幾眼炮捧,就能明白一個(gè)系統(tǒng)所用的架構(gòu),自然就能夠直接聯(lián)想到其中會(huì)存在的角色惦银,以及角色間的關(guān)系咆课。?

然而,并不是每個(gè)系統(tǒng)所用的架構(gòu)扯俱,都是大眾所熟悉书蚪,或是一眼能夠望穿的。這時(shí)候迅栅,你需要探索殊校。目標(biāo)同樣要放在界定其中的角色、以及角色間的靜態(tài)读存、動(dòng)態(tài)關(guān)系箩艺。?

不 論某個(gè)系統(tǒng)所采用的架構(gòu)是否為大部分人所熟知的窜醉,在試著探索一個(gè)系統(tǒng)的長相時(shí),我們應(yīng)該找出來幾個(gè)答案艺谆,了解在它所用的架構(gòu)下,下列這件事是如何被完成 的:一拜英、系統(tǒng)如何初始化静汤,二、與這個(gè)系統(tǒng)相接的其他系統(tǒng)(或用戶)有那些居凶,而相接的接口又是什么虫给;三、系統(tǒng)如何反應(yīng)各種事件侠碧,四抹估、系統(tǒng)如何處理各種異常及 錯(cuò)誤。?

系統(tǒng)如何初始化是很重要的一件事弄兜,因?yàn)槌跏蓟菫榱私酉聛淼乃惺挛锒龅臏?zhǔn)備药蜻。從初始化的方式、內(nèi)容替饿,能知道系統(tǒng)做了什么準(zhǔn)備语泽,對于系統(tǒng)會(huì)有什么行為展現(xiàn),也就能得窺一二了视卢。?

之所以要了解與系統(tǒng)相接的其他系統(tǒng)(或用戶)踱卵,為的是要界定出系統(tǒng)的邊界。其他的系統(tǒng)可能會(huì)提供輸入給我們所探索的系統(tǒng)据过,也可能接收來自這系統(tǒng)的輸出惋砂,了解這邊界所在,才能確定系統(tǒng)的外觀绳锅。?

而系統(tǒng)所反應(yīng)的事件類型西饵、以及如何反應(yīng),基本上就代表著系統(tǒng)本身的主要行為模式榨呆。最后罗标,我們必須了解系統(tǒng)處理異常及錯(cuò)誤的方式,這同樣也是系統(tǒng)的重要行為积蜻,但容易被忽略闯割。?

之前,我們提到必須先具備一個(gè)系統(tǒng)的語言基礎(chǔ)竿拆,才能夠進(jìn)一步加以閱讀宙拉,而在本文中,我們的重點(diǎn)放在:要了解一個(gè)系統(tǒng)丙笋,最好是采取由上至下的方式谢澈。先試著捕捉系統(tǒng)架構(gòu)性的觀念撕瞧,不要過早鉆進(jìn)細(xì)節(jié)皆撩,因?yàn)槟峭ǔτ谀懔私馊玻瑳]有多大的幫助。?

三独令、優(yōu)質(zhì)工具在手,讀懂程序非難事?

系統(tǒng)的復(fù)雜度往往超過人腦的負(fù)荷间唉。閱讀程序代碼的時(shí)候偏塞,你會(huì)需要更多工具提供協(xié)助。使用好的集成開發(fā)環(huán)境(IDE)或文本編輯器钉答,就能提供最基本的幫助础芍。

閱讀程序代碼的動(dòng)作,可以是很原始的数尿,利用最簡單的文本編輯器仑性,逐一開啟原始碼,然后憑借著一己的組織能力右蹦,在不同的程序代碼間跳躍诊杆,拼湊出腦中想要構(gòu)建的圖像。?

不過嫩实,系統(tǒng)的復(fù)雜度往往超過人腦的負(fù)荷刽辙。閱讀程序代碼的時(shí)候,你會(huì)需要更多工具提供協(xié)助甲献。使用好的集成開發(fā)環(huán)境(IDE)或文本編輯器宰缤,就能提供最基本的幫助。?

善用文本編輯器或IDE晃洒,加速解讀程序代碼?

許 多文本編輯器提供了常見程序語言的語法及關(guān)鍵詞標(biāo)示功能慨灭。這對于閱讀來說,絕對能夠起很大的作用球及。有些文本編輯器(例如我常用的EditPlus及偶而使 用的Notepad++)氧骤,甚至能夠自動(dòng)列出某個(gè)原始檔中所有定義的函式清單,更允許你直接從清單中選擇函式吃引,直接跳躍到該函式的定義位置筹陵。這對于閱讀程 序代碼的人來說,就提供了極佳的便利性镊尺。?

因?yàn)樵陂喿x程序代碼時(shí)朦佩,最常做的事,就是隨著程序中的某個(gè)控制流庐氮,將閱讀的重心语稠,從某個(gè)函式移至它所呼叫的另一個(gè)函式。所以對程序人來說,閱讀程序代碼時(shí)最常做的事之一就是:找出某個(gè)函式位在那一個(gè)原始檔里仙畦,接著找到該函式所在的位置输涕。?

好的IDE能夠提供的協(xié)助就更多了。有些能夠自動(dòng)呈現(xiàn)一些額外的信息慨畸,最有用的莫過于函式的原型宣告了莱坎。例如,有些IDE支持當(dāng)光標(biāo)停留在某函式名稱上一段時(shí)間后寸士,它會(huì)以Tooltip的方式顯示該函式的原型宣告型奥。?

對閱讀程序代碼的人來說,在看到程序代碼中呼叫到某個(gè)函式時(shí)碉京,可以直接利用這樣的支持,立即取得和這個(gè)函式有關(guān)的原型信息螟深,馬上就能知道呼叫該函式所傳入的各個(gè)自變量的意義谐宙,而不必等到將該函式的定義位置找出后,才能明白這件事界弧。?

grep是一個(gè)基本而極為有用的工具?

除 了選用好的文本編輯器或IDE之外凡蜻,還有一個(gè)基本、但卻極為有用的工具垢箕,它就是grep划栓。熟悉Unix操作系統(tǒng)的程序人,對grep這個(gè)公用程序多半都不 陌生条获。Grep最大的用途忠荞,在于它允許我們搜尋某個(gè)目錄(包括遞歸進(jìn)入所有子目錄)中所有指定檔案,是否有符合指定條件(常數(shù)字符串或正規(guī)表示式)檔 案帅掘。?

倘若有的話委煤,則能幫你指出所在的位置。這在閱讀程序代碼時(shí)的作用極大修档。當(dāng)我們隨著閱讀的腳步碧绞,遇上了任何一個(gè)不認(rèn)識(shí)、但自認(rèn)為重要的類別吱窝、函式讥邻、數(shù)據(jù)結(jié)構(gòu)定義或變量,我們就得找出它究竟位在這茫茫程序代碼海中的何處院峡,才能將這個(gè)圖塊從未知變?yōu)橐阎?

grep 之所以好用兴使,就是在于當(dāng)我們發(fā)現(xiàn)某個(gè)未知的事物時(shí),可以輕易地利用它找出這個(gè)未知的事物究竟位在何方撕予。此外鲫惶,雖說grep是Unix的標(biāo)準(zhǔn)公用程序之一, 但是像Windows這樣子的平臺(tái)实抡,也有各種類型的grep程序欠母。對于在Windows環(huán)境工作的程序人來說欢策,可以自行選用覺得稱手的工具。?

gtags可建立索引赏淌,讓搜尋更有效率?

grep雖然好用踩寇,但是仍然有一些不足之處。第一個(gè)缺點(diǎn)在于它并不會(huì)為所搜尋的原始碼檔案索引六水。每當(dāng)你搜尋時(shí)俺孙,它都會(huì)逐一地找出所有的檔案,并且讀取其中的所有內(nèi)容掷贾,過濾出滿足指定條件的檔案睛榄。當(dāng)項(xiàng)目的原始碼數(shù)量太大時(shí),就會(huì)產(chǎn)生搜尋效率不高的問題想帅。?

第二個(gè)缺點(diǎn)是它只是一個(gè)單純的文本文件搜尋工具场靴,本身并不會(huì)剖析原始碼所對應(yīng)的語言語法。當(dāng)我們只想針對「函式」名稱進(jìn)行搜尋時(shí)港准,它有可能將批注中含有該名稱的原始碼旨剥,也一并找了出來。?


針 對grep的缺點(diǎn)浅缸,打算閱讀他人程序代碼的程序人轨帜,可以考慮使用像是gtags這樣子的工具。gtags是GNU GLOBAL source code tag system衩椒,它不只搜尋文字層次蚌父,而且因?yàn)榫邆淞烁鞣N語言的語法剖析器,所以在搜尋時(shí)烟具,可以只針對和語言有關(guān)的元素梢什,例如類別名稱、函式名稱等朝聋。?

而且嗡午,它能針對原始碼的內(nèi)容進(jìn)行索引,這意謂一旦建好索引之后冀痕,每次搜尋的動(dòng)作荔睹,都毋需重新讀取所有原始碼的內(nèi)容并逐一搜尋。只需要以現(xiàn)成的索引結(jié)構(gòu)為基礎(chǔ)言蛇,即可有效率的尋找關(guān)鍵段落僻他。?

gtags 提供了基于命令行的程序,讓你指定原始碼所在的目錄執(zhí)行建立索引的動(dòng)作腊尚。它同時(shí)也提供程序讓你得如同操作grep一般吨拗,針對索引結(jié)構(gòu)進(jìn)行搜尋及檢索。它提 供了許多有用的檢索方式,例如找出項(xiàng)目中定義某個(gè)數(shù)據(jù)結(jié)構(gòu)的檔案及定義所在的行號(hào)劝篷,或者是找出項(xiàng)目中所有引用某數(shù)據(jù)結(jié)構(gòu)的檔案哨鸭,以及引用處的行號(hào)。?

這么一來娇妓,你就可以輕易地針對閱讀程序代碼時(shí)的需求予以檢索像鸡。相較于grep所能提供的支持,gtags這樣的工具哈恰,簡直是強(qiáng)大許多只估。?

再搭配htags制作HTML文件,更是如虎添翼?

還 有一個(gè)絕對需要一提的工具着绷。這個(gè)叫做htags的工具蛔钙,能夠幫你將已制作完成的索引結(jié)構(gòu),制作成為一組相互參考的HTML文件荠医】溟梗基本上,利用這樣的 HTML文件閱讀程序代碼子漩,比起單純地直接閱讀原始碼,來得更有結(jié)構(gòu)石洗。原因是閱讀程序代碼時(shí)幢泼,這樣的HTML文件,已經(jīng)為你建立起在各個(gè)原始碼檔案片段間 跳躍的鏈結(jié)讲衫。例如缕棵,圖一(略)是針對一個(gè)有名的開放原始碼項(xiàng)目ffmpeg,由gtags所產(chǎn)生出來的HTML文件首頁的一部分涉兽。?

htags工具首先為你找出所有定義main()函式的檔案招驴,并且列出所在的函式。找出main()函式枷畏,時(shí)常是閱讀程序代碼的第一步别厘,因?yàn)閙ain()函式是程序的主要入口點(diǎn),所有的動(dòng)作皆由此啟動(dòng)拥诡,它是一切事物的源頭触趴。?

憑借htags制作的HTML文件,你可以輕易地點(diǎn)擊超鏈接渴肉,直接進(jìn)到main()函式所在的代碼段冗懦,如圖二(略)。?

當(dāng)我們檢視上述原始碼時(shí)仇祭,發(fā)現(xiàn)av_register_all()是個(gè)陌生披蕉、無法了解的事物,而想要搞懂它究竟是什么,可以再繼續(xù)點(diǎn)擊這個(gè)函式没讲,如圖三(略)眯娱。這真是太方便了!閱讀至此食零,你會(huì)猛然發(fā)現(xiàn)困乒,gtags彷佛就是為了閱讀程序代碼而專門量身打造的利器。?

?提問/互動(dòng)請留言贰谣,可直接在最底右下方"寫留言即可

?Java初高級(jí)一起學(xué)習(xí)分享娜搂,共同學(xué)習(xí)才是最明智的選擇,喜歡的話可以我的學(xué)習(xí)群64弍46衣3凌9吱抚,或加資料群69似64陸0吧3(進(jìn)群備注簡書)

?如果覺得寫得不錯(cuò)請點(diǎn)擊“訂閱”百宇,每天更新全新的內(nèi)容!

?你們的喜歡和關(guān)注就是我最大的動(dòng)力支撐C乇P!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末既绕,一起剝皮案震驚了整個(gè)濱河市啄刹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凄贩,老刑警劉巖誓军,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異疲扎,居然都是意外死亡昵时,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門椒丧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壹甥,“玉大人,你說我怎么就攤上這事壶熏【淠” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵棒假,是天一觀的道長俄占。 經(jīng)常有香客問我,道長淆衷,這世上最難降的妖魔是什么缸榄? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮祝拯,結(jié)果婚禮上甚带,老公的妹妹穿的比我還像新娘她肯。我一直安慰自己,他們只是感情好鹰贵,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布晴氨。 她就那樣靜靜地躺著,像睡著了一般碉输。 火紅的嫁衣襯著肌膚如雪籽前。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天敷钾,我揣著相機(jī)與錄音枝哄,去河邊找鬼。 笑死阻荒,一個(gè)胖子當(dāng)著我的面吹牛挠锥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侨赡,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蓖租,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了羊壹?” 一聲冷哼從身側(cè)響起蓖宦,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎油猫,沒想到半個(gè)月后球昨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眨攘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嚣州。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鲫售。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖该肴,靈堂內(nèi)的尸體忽然破棺而出情竹,到底是詐尸還是另有隱情,我是刑警寧澤匀哄,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布秦效,位于F島的核電站,受9級(jí)特大地震影響涎嚼,放射性物質(zhì)發(fā)生泄漏阱州。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一法梯、第九天 我趴在偏房一處隱蔽的房頂上張望苔货。 院中可真熱鬧犀概,春花似錦、人聲如沸夜惭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诈茧。三九已至产喉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敢会,已是汗流浹背曾沈。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留走触,地道東北人晦譬。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像互广,于是被迫代替她去往敵國和親敛腌。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 我們在寫程序時(shí)惫皱,有不少時(shí)間都是在看別人的代碼像樊。 例如看小組的代碼,看小組整合的守則旅敷,若一開始沒規(guī)劃怎么看生棍, 就會(huì)看...
    梁睿坤閱讀 3,667評(píng)論 1 9
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,321評(píng)論 25 707
  • 廈門是一個(gè)充滿情懷的城市。來了媳谁,便不想再離開涂滴。那時(shí)候,我一直想著要生活在一個(gè)有海的城市晴音,于是畢業(yè)后柔纵,我便一...
    迎慶心烘焙閱讀 469評(píng)論 5 1
  • 落日染紅了西南角 朦朧了高樓 壓低了孤樹 襯托了落日
    大唐御弟閱讀 100評(píng)論 0 0
  • 一、前言 OpenFace是在深度學(xué)習(xí)開源框架torch上實(shí)現(xiàn)的基于python語言的人臉識(shí)別開源框架锤躁,其使用的算...
    閃電隨筆閱讀 10,440評(píng)論 5 3