如何讀懂代碼

Code Code Code

我們在寫程序時(shí),有不少時(shí)間都是在看別人的代碼骇吭。 例如看小組的代碼,看小組整合的守則歧寺,若一開始沒規(guī)劃怎么看燥狰, 就會(huì)看得云山霧罩不知其所然。

不管是參考也好斜筐,從開源抓下來研究也好龙致,為了了解箇中含意,在有限的時(shí)間下顷链,不免會(huì)對龐大的源代碼解讀感到壓力目代。

以下來介紹一下讀代碼的心法:

  1. 讀懂程序代碼,使心法皆為我所用嗤练。
  2. 摸清架構(gòu)榛了,便可輕松掌握全貌。
  3. 優(yōu)質(zhì)工具在手煞抬,讀懂程序非難事霜大。
  4. 望文生義,進(jìn)而推敲組件的作用革答。
  5. 找到程序入口战坤,再由上而下抽絲剝繭曙强。
  6. 閱讀的樂趣,透過程序認(rèn)識作者湖笨。

讀懂程序旗扑,使心法皆為我所用

程序是別人寫的,只有原作者才真的了解程序的用途及涵義慈省。許多程員心里都有一種不自覺的恐懼感臀防,深怕被迫去碰觸其他人所寫的程序。但是边败,與其抗拒接收別人的程序袱衷,不如徹底了解相關(guān)的語言和慣例,當(dāng)成是培養(yǎng)自我實(shí)力的基石笑窜。

對大多數(shù)的程序員來說致燥,撰寫程序或許是令人開心的一件事情,但我相信排截,有更多人視閱讀他人所寫成的程序?yàn)槲吠鞠釉椤TS多人寧可自己重新寫過一遍程序,也不愿意接收別人的程序断傲,進(jìn)而修正錯(cuò)誤脱吱,維護(hù)它們,甚至加強(qiáng)功能认罩。

這其中的關(guān)鍵究竟在何處呢箱蝠?若是一語道破,其實(shí)也很簡單垦垂,程序是別人寫的宦搬,只有原作者才真的了解程序的用途及涵義。許多程序員心里都有一種不自覺的恐懼感劫拗,深怕被迫去碰觸其他人所寫的程序间校。這是來自于人類內(nèi)心深處對于陌生事物的原始恐懼。

讀懂別人寫的程序杨幼,讓你收獲滿滿撇簿。不過,基于許多現(xiàn)實(shí)的原因差购,程序員時(shí)常受迫要去接收別人的程序四瘫。例如,同事離職了欲逃,必須接手他遺留下來的工作找蜜,也有可能你是剛進(jìn)部門的菜鳥,而同事經(jīng)驗(yàn)值夠了稳析,升級了洗做,風(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)氣如此盛行的今日,你可以透過開放源碼學(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)致最后只能入寶山空手回吱雏,望之興嘆敦姻。

接觸他人的程序,大致上可以分為三種程度:

  1. 了解
  2. 修改坎背,擴(kuò)充
  3. 抽取替劈,提煉。

了解別人的程序是最基礎(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í)現(xiàn)時(shí)蝉揍,能夠很快在腦上對映到具體的程序員位置链峭,直到那一刻,才是細(xì)讀的時(shí)機(jī)又沾。

熟悉溝通語言與慣例用語

不論如何弊仪,有些基本的準(zhǔn)備,是閱讀他人程序員時(shí)必須要有的杖刷。

首先励饵,你最好得了解程序員使用的編程語言。想要讀懂法文寫成的小說滑燃,總不能連法文都不懂吧役听。有些情況則很特殊。我們雖然不懂該程序員撰寫所用的語言表窘,但是因?yàn)楝F(xiàn)代語言的高階化典予,而且流行的編程語言多半都是血統(tǒng)相近,所以即使不那么熟悉乐严,有時(shí)也可勉力為之瘤袖。

除了認(rèn)識所用語言之外,再來就是要先確認(rèn)程序員所用的命名慣例(命名慣例) 昂验。了解命名慣例很重要捂敌,不同的程序員或開發(fā)團(tuán)隊(duì),差異可能很大既琴。

這命名慣例涵蓋的范圍通常包括了變數(shù)的名稱黍匾,函數(shù)的名稱,類別(如果是面向?qū)ο蟮脑挘┑拿Q呛梆,源代碼檔案,甚至是項(xiàng)目建構(gòu)目錄的名稱磕诊。倘若使用了像設(shè)計(jì)模式之類的方法填物,這些名稱更有一些具體的表述方式。

命名慣例有點(diǎn)像是程序員在編程語言之上霎终,另行建構(gòu)的一組溝通行話滞磺。程序員會(huì)透過共通約束,遵守的命名慣例莱褒,來表達(dá)一些較高階的概念击困。例如,有名的匈牙利式命名法,便將變數(shù)名稱以屬性阅茶,型別蛛枚,說明合并在一起描述。對程序員來說脸哀,這種方式能夠提供更豐富的資訊蹦浦,以了解該變數(shù)的作用及性質(zhì)。

對程序員閱讀來說撞蜂,熟悉這個(gè)做法之所以重要盲镶,是因?yàn)楫?dāng)你了解整個(gè)系統(tǒng)所采用的慣例時(shí),你便能試著以他們所共同操用的語匯來進(jìn)行理解蝌诡。倘若溉贿,不能了解其所用的慣例,那么這些額外提供的資訊浦旱,就無法為你所用宇色。像以設(shè)計(jì)模式寫成的程序員,同樣處處充滿著模式的名稱闽寡,諸如:工廠代兵,門面,代理等等爷狈。以這些名稱指涉的類別植影,也直接透過名稱,表達(dá)了它們自身的作用涎永。對于懂得這命名慣例的讀者來說思币,不需要深入探索,也能很快捕捉到這些類別的意義羡微。

當(dāng)你拿到一套必須閱讀的程序員時(shí)谷饿,最好先取得命名慣例的說明文件。然而妈倔,并不是每套程序員都附有此類的說明文件博投。另一個(gè)方式,就是自己到程序員中盯蝴,大略瀏覽一遍毅哗,有經(jīng)驗(yàn)的程序員可以輕易發(fā)掘出該系統(tǒng)所用的命名慣例。

常見的命名方式不脫那幾類捧挺,這時(shí)候經(jīng)驗(yàn)就很重要虑绵,倘若你知道的慣例越多,就越能輕易識別他人所用的慣例闽烙。如果運(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)槌撬呛芎唵蔚膯螆?zhí)行緒程序绍傲,否則很少這么做扔傅。因?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)識请梢。

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

如果你想要跳脫困境,不想浪費(fèi)大量時(shí)間閱讀程序員毅弧,卻始終只能捕捉到對系統(tǒng)片段認(rèn)識气嫁,就必須轉(zhuǎn)換到另一種觀點(diǎn)來看待系統(tǒng)。從個(gè)別的類別行為著手够坐,是由下至上(自下而上)的方法;在閱讀程序員時(shí)寸宵,卻應(yīng)該先采由上至下(自上而下)的方式崖面。對程序員的閱讀來說,由上至下意謂著梯影,你得先了解整個(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容器)為根本。

使用的Java Servlet的/ JSP的技術(shù)時(shí)拷泽,決定了某些組成之間的關(guān)系疫鹊。例如, Web容器依據(jù)web.xml中的內(nèi)容載入所有的Servlets 司致,聽眾拆吆,以及過濾器。每當(dāng)語境發(fā)生事件(例如初始化)時(shí)脂矫,它便會(huì)通知監(jiān)聽類別枣耀。每當(dāng)它收到來自客戶端的請求時(shí),便會(huì)依循設(shè)定的所有過濾器鏈庭再,讓每個(gè)過濾器都有機(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)的服務(wù)器來處理它。當(dāng)想要關(guān)注某個(gè)請求如何處理時(shí)斧抱,我應(yīng)該去找出這個(gè)請求對應(yīng)的服務(wù)器常拓。

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

同樣的辉浦,以爪哇寫成的網(wǎng)頁應(yīng)用程序中弄抬,也許會(huì)應(yīng)用諸如Struts的之類的的MVC框架,以及像Hibernate的這樣的資料存取框架宪郊。它們都可以視為最主要的架構(gòu)下的較次級架構(gòu)掂恕。而各個(gè)應(yīng)用系統(tǒng)荔茬,甚至有可能在Struts的及休眠之下,建立自有的更次級的架構(gòu)竹海。

也就是說,當(dāng)我們談到“架構(gòu)”這樣的觀念時(shí)丐黄,必須要有層次感斋配。而不論是那一層級的架構(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è)是事件處理的分派器(事件調(diào)度) 璧亮,一個(gè)是事件產(chǎn)生者(事件發(fā)生器) 萧诫,另一個(gè)則是事件處理器(事件處理程序) 。

事件產(chǎn)生器產(chǎn)生事件枝嘶,并送至事件分派器帘饶,而事件分派器負(fù)責(zé)找出各事件相對應(yīng)的事件處理器,并且轉(zhuǎn)交該事件躬络,并命令事件處理器加以處理尖奔。像的圖形用戶界面的Windows應(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)識峭火。

雖然你還不清楚所有的細(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)示功能吻氧。這對于閱讀來說溺忧,絕對能夠起很大的作用。有些文字編輯器(例如我常用的編輯器及偶而使用的記事本+ + )盯孙,甚至能夠自動(dòng)列出某個(gè)原始檔中所有定義的函數(shù)清單鲁森,更允許你直接從清單中選擇函數(shù),直接跳躍到該函數(shù)的定義位置振惰。這對于閱讀程序員的人來說歌溉,就提供了極佳的便利性。

因?yàn)樵陂喿x程序員時(shí)骑晶,最常做的事痛垛,就是隨著程序中的某個(gè)控制流,將閱讀的重心桶蛔,從某個(gè)函數(shù)移至它所調(diào)用的另一個(gè)函數(shù)匙头。所以對程序員來說,閱讀程序員時(shí)最常做的事之一就是:找出某個(gè)函數(shù)位在那一個(gè)原始檔里仔雷,接著找到該函數(shù)所在的位置蹂析。

好的的IDE能夠提供的協(xié)助就更多了。有些能夠自動(dòng)呈現(xiàn)一些額外的資訊碟婆,最有用的莫過于函數(shù)的原型宣告了识窿。例如,有些的IDE支援當(dāng)游標(biāo)停留在某函數(shù)名稱上一段時(shí)間后脑融,它會(huì)以提示的方式顯示該函數(shù)的原型宣告喻频。

對閱讀程序員的人來說,在看到程序員中調(diào)用到某個(gè)函數(shù)時(shí)肘迎,可以直接利用這樣的支援甥温,立即取得和這個(gè)函數(shù)有關(guān)的原型資訊,馬上就能知道調(diào)用該函數(shù)所傳入的各個(gè)引數(shù)的意義妓布,而不必等到將該函數(shù)的定義位置找出后姻蚓,才能明白這件事。

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

除了選用好的文字編輯器或的IDE 之外匣沼,還有一個(gè)基本狰挡,但卻極為有用的工具,它就是grep。熟悉的Unix/Linux系統(tǒng)的程序員對grep這個(gè)程序多半都不陌生加叁。 grep 最大的用途倦沧,在于它允許我們搜尋某個(gè)目錄(包括遞回進(jìn)入所有子目錄)中所有指定檔案,是否有符合指定條件(常數(shù)字串或正規(guī)表示式)檔案它匕。

倘若有的話展融,則能幫你指出所在的位置。這在閱讀程序員時(shí)的作用極大豫柬。當(dāng)我們隨著閱讀的腳步告希,遇上了任何一個(gè)不認(rèn)識,但自認(rèn)為重要的類別烧给,函數(shù)燕偶,資料結(jié)構(gòu)定義或變數(shù),我們就得找出它究竟位在這茫茫程序員海中的何處础嫡,才能將這個(gè)圖塊從未知變?yōu)橐阎?/p>

grep之所以好用指么,就是在于當(dāng)我們發(fā)現(xiàn)某個(gè)未知的事物時(shí),可以輕易地利用它找出這個(gè)未知的事物究竟位在何方驰吓。此外,雖說grep按是Unix系統(tǒng)的標(biāo)準(zhǔn)公用程序之一系奉,但是像視窗這樣子的平臺(tái)檬贰,也有各種類型的grep命令。對于在視窗環(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)我們只想針對“函數(shù)”名稱進(jìn)行搜尋時(shí),它有可能將注解中含有該名稱的源代碼咏闪,也一并找了出來曙搬。

針對grep的缺點(diǎn),打算閱讀他人程序員的程序員,可以考慮使用像是gtags這樣子的工具纵装。 gtags是源代碼的GNU全局標(biāo)記系統(tǒng)征讲,它不只搜尋文字層次,而且因?yàn)榫邆淞烁鞣N語言的語法剖析器搂擦,所以在搜尋時(shí)稳诚,可以只針對和語言有關(guān)的元素,例如類別名稱瀑踢,函數(shù)名稱等扳还。

而且,它能針對源代碼的內(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è)資料結(jié)構(gòu)的檔案及定義所在的行號,或者是找出項(xiàng)目中所有引用某資料結(jié)構(gòu)的檔案巧骚,以及引用處的行號赊颠。

這么一來,你就可以輕易地針對閱讀程序員時(shí)的需求予以檢索劈彪。相較于grep 按所能提供的支援竣蹦,gtags這樣的工具,簡直是強(qiáng)大許多沧奴。

望文生義痘括,進(jìn)而推敲組件的作用

先建立系統(tǒng)的架構(gòu)性認(rèn)識,然后透過名稱及命名慣例滔吠,就可以推測出各組件的作用远寸。例如:當(dāng)AOL的Winamp嘗試著初始化一個(gè)插件時(shí),它會(huì)調(diào)用這個(gè)結(jié)構(gòu)中的初始化函數(shù)屠凶,以便讓每個(gè)插件程序有機(jī)會(huì)初始化自己驰后。當(dāng)AOL的Winamp打算結(jié)束自己或結(jié)束某個(gè)插件的執(zhí)行時(shí),便會(huì)調(diào)用結(jié)束函數(shù)矗愧。

在閱讀程序的細(xì)節(jié)之前灶芝,我們應(yīng)先試著捕捉系統(tǒng)的運(yùn)作情境郑原。在采取由上至下的方式時(shí),系統(tǒng)性的架構(gòu)是最頂端的層次夜涕,而系統(tǒng)的運(yùn)作情境鸦难,則是在它之下的另一個(gè)層次铆铆。

好的說明文件難求,拼湊故事的能力很重要

有些系統(tǒng)提供良善的說明文件,也許還利用UML的充分描述系統(tǒng)的運(yùn)行情況芽偏。那么對于閱讀者來說长赞,從系統(tǒng)的分析及設(shè)計(jì)文件著手渠啤,便是快速了解系統(tǒng)運(yùn)作情境的一個(gè)途徑跛锌。

但是,并不是每個(gè)軟件項(xiàng)目都伴隨著良好的系統(tǒng)文件丧诺,而許多極具價(jià)值的開放源代碼項(xiàng)目入桂,也時(shí)常不具備此類的文件。對此驳阎,閱讀者必須嘗試自行捕捉抗愁,并適度地記錄捕捉到的運(yùn)作情境。

我喜歡將系統(tǒng)的運(yùn)作情境呵晚,比擬成系統(tǒng)會(huì)上演的故事情節(jié)蜘腌。在閱讀細(xì)節(jié)性質(zhì)的程序員前,先知道系統(tǒng)究竟會(huì)發(fā)生那些故事饵隙,是必備的基本功課撮珠。你可以利用熟悉或者自己發(fā)明的表示工具,描述你所找到的情境癞季。甚至可以只利用簡單的列表劫瞳,直接將它們列出倘潜。只要能夠達(dá)到記錄的目的绷柒,對程序員閱讀來說,都能夠提供幫助涮因》夏溃或者,你也可以利用基于UML中的類別圖养泡,合作圖嗜湃,循序圖之類的表示方法,做出更詳細(xì)的描述澜掩。
當(dāng)你能夠列出系統(tǒng)可能會(huì)有的情境购披,表示你對系統(tǒng)所具備的功能,以及在各種情況下的反應(yīng)肩榕,都具備概括性的認(rèn)識刚陡。以此為基礎(chǔ),便可在任何需要的時(shí)候,鉆進(jìn)細(xì)節(jié)處深入了解筐乳。

探索架構(gòu)的第一步──找到程序的入口

在之前歌殃,我們在一個(gè)開發(fā)項(xiàng)目中,曾經(jīng)需要將系統(tǒng)所得到的的MP3音訊檔蝙云,放至iPod的這個(gè)極受歡迎的播放設(shè)備中氓皱。

雖然iPod的本身也可以做為可移動(dòng)式的儲(chǔ)存設(shè)備,但并不是單純地將MP3播放檔案放到中的iPod 勃刨,就可以讓蘋果的播放器認(rèn)得這個(gè)檔案波材,甚至能夠加以播放。
這是因?yàn)樘O果利用一個(gè)特殊的檔案結(jié)構(gòu)( iTunes的數(shù)據(jù)庫) 朵你,記錄播放器中可供播放的樂曲各聘,播放清單以及樂曲資訊(例如專輯名稱,樂曲長度抡医,演唱者等) 躲因。為了了解并且試著重復(fù)使用既有的程序員,我們找到了一個(gè)AOL的Winamp的iPod的外掛程序(插件) 忌傻。

AOL的Winamp是個(gè)人電腦上極受歡迎的播放軟件大脉,而我們找到的外掛程序,能讓的軟件直接顯示連接至電腦的的iPod中的歌曲資訊水孩,并且允許的軟件直接播放镰矿。

我們追蹤與閱讀這個(gè)外掛程序的思路及步驟如下,首先俘种,我們要先了解外掛程序的系統(tǒng)架構(gòu)秤标。很明顯的,大概瀏覽過源代碼后宙刘,我們注意到它依循著AOL的Winamp為插件程序所制定的規(guī)范苍姜,也就是說,它是實(shí)現(xiàn)成的Windows上的DLL的悬包,并且透過一個(gè)叫做winampGetMediaLibraryPlugin的DLL的函數(shù)衙猪,提供一個(gè)名為winampMediaLibraryPlugin的結(jié)構(gòu)。
當(dāng)我們不清楚系統(tǒng)的架構(gòu)究竟為何時(shí)布近,我們會(huì)試著探索垫释,而第一步,便是找到程序的入口撑瞧。如何找到呢棵譬?這會(huì)依程序的性質(zhì)不同而有所差別。
對一個(gè)本身就是可獨(dú)立執(zhí)行的程序來說预伺,我們會(huì)找啟動(dòng)程序的主要函數(shù)订咸,例如對的C/C++來說就是main()函數(shù)琅束,而對Java來說,便是靜態(tài)方法main() 算谈。在找到入口后涩禀,再逐一追蹤,摸索出系統(tǒng)的架構(gòu)然眼。

但有時(shí)艾船,我們閱讀的程序如果是類庫或函數(shù)庫,本身并不具單一入口高每,此類的程序具有多重的入口──每個(gè)允許用戶端程序調(diào)用的函數(shù)或類別屿岂,都是它可能的入口。

例如鲸匿,對AOL的Winamp的 iPod的插件來說爷怀,它是一個(gè)動(dòng)態(tài)鏈接庫形式的函數(shù)庫,所以當(dāng)我們想了解它的架構(gòu)時(shí)带欢,必須要先找出它對外提供的函數(shù)运授,而對的Windows的DLL來說,對外提供的函數(shù)乔煞,皆會(huì)以dllexport這個(gè)關(guān)鍵字來修飾吁朦。所以,不論是利用grep按或gtags之類的工具渡贾,我們可以很快從源代碼中逗宜,找到它只有一個(gè)DLL的函數(shù)(這對我們而言,真是一個(gè)好消息) 空骚,而這個(gè)函數(shù)便是上述的winampGetMediaLibraryPlugin 纺讲。

系統(tǒng)多會(huì)采用相同的架構(gòu)處理插件程序

如果經(jīng)驗(yàn)不夠的話,也許無法直接猜出這個(gè)函數(shù)的作用囤屹。 不過熬甚,如果你是個(gè)有經(jīng)驗(yàn)的程序員,多半能從函數(shù)所回傳的結(jié)構(gòu)牺丙,猜出這個(gè)函數(shù)實(shí)際的用途则涯。而事實(shí)上复局,當(dāng)你已經(jīng)知道它是一個(gè)插件程序時(shí)冲簿,就應(yīng)該要明白,它可能采用的亿昏,就是許多系統(tǒng)都采用的相同架構(gòu)處理插件程序峦剔。

當(dāng)一個(gè)系統(tǒng)采用所謂插件形式的架構(gòu)時(shí),它通常不會(huì)知道它的插件究竟會(huì)怎么實(shí)現(xiàn)角钩,實(shí)現(xiàn)什么功能吝沫。它只會(huì)規(guī)范插件程序需要滿足某個(gè)特定界面呻澜。當(dāng)系統(tǒng)初始化時(shí),所有的插件都可以依循相同的方式惨险,向系統(tǒng)注冊羹幸,合法宣示自己的存在。

雖然系統(tǒng)并不確切知道插件會(huì)有什么行為展現(xiàn)辫愉,但是因?yàn)樗贫艘粋€(gè)標(biāo)準(zhǔn)的界面栅受,所以系統(tǒng)仍然可以預(yù)期每個(gè)插件能夠處理的動(dòng)作類型。這些動(dòng)作具體上怎么執(zhí)行恭朗,對系統(tǒng)來說并不重要屏镊。這也正是面向?qū)ο蟪绦蛟O(shè)計(jì)中的“多態(tài)”觀念。

隨著實(shí)踐經(jīng)驗(yàn)痰腮,歸納常見的架構(gòu)模式

我想表達(dá)的重點(diǎn)而芥,是當(dāng)你“涉世越深”之后,所接觸的架構(gòu)越多膀值,就越能觸類旁通棍丐。只需要瞧上幾眼,就能明白系統(tǒng)所用的架構(gòu)沧踏,自然就能夠直接聯(lián)想到其中可能存在的角色骄酗,以及角色間的關(guān)系。

像上述的插件程序手法悦冀,時(shí)城鞣可以在許多允許“外掛”程序員的系統(tǒng)中看到。所以盒蟆,有經(jīng)驗(yàn)的閱讀者踏烙,多半能夠立即反應(yīng),知道像這樣的系統(tǒng)的軟件历等,應(yīng)該是讓每個(gè)插件程序讨惩,都寫成DLL的函數(shù)庫。

而每個(gè)插件的DLL的函數(shù)庫中寒屯,都必須提供winampGetMediaLibraryPlugin()這個(gè)函數(shù) 荐捻。如果你熟悉設(shè)計(jì)模式,你更會(huì)知道這是簡單工廠方法這個(gè)設(shè)計(jì)模式的運(yùn)用寡夹。
winampGetMediaLibraryPlugin() 所回傳的winampMediaLibraryPlugin結(jié)構(gòu)处面,正好就描述了每個(gè)AOL的Winamp插件的實(shí)現(xiàn)內(nèi)容。

善用名稱可加速了解

利用gtags這個(gè)工具菩掏,我們立即發(fā)現(xiàn)魂角,這個(gè)插件它所定義的初始化,退出智绸, PluginMessageProc這三個(gè)名稱野揪,都是函數(shù)名稱访忿。這暗示在方法重載的作用下,它們都是在某些時(shí)間點(diǎn)斯稳,會(huì)由AOL的Winamp核心本體調(diào)用的函數(shù)海铆。

名稱及命名慣例是很重要的≌醵瑁看到 “初始化” 游添,我們會(huì)知道它的作用多半是進(jìn)行初始化的動(dòng)作,而“退出”大概就是結(jié)束時(shí)處理函數(shù)通熄,而PluginMessageProc多半就是各種訊息的處理常式(過程通常是程序的簡寫唆涝,所以PluginMessageProc意指插件訊息程序)了。

“望文生義”很重要唇辨,我們看到函數(shù)的名稱廊酣,就可以猜想到它所代表的作用,例如:當(dāng)AOL的Winamp嘗試著初始化一個(gè)插件時(shí)赏枚,它會(huì)調(diào)用這個(gè)結(jié)構(gòu)中的初始化函數(shù)亡驰,以便讓每個(gè)插件程序有機(jī)會(huì)初始化自己;當(dāng)AOL的Winamp打算結(jié)束自己或結(jié)束某個(gè)插件的執(zhí)行時(shí),便會(huì)調(diào)用退出函數(shù)饿幅。當(dāng)AOL的Winamp要和插件程序溝通時(shí)凡辱,它會(huì)發(fā)送各種不同的訊息至插件,而插件程序必須對此做出回應(yīng)栗恩。

我們甚至不需要檢查這幾個(gè)函數(shù)的內(nèi)容透乾,就可以做出推測,而這樣的假設(shè)磕秤,事實(shí)上也是正確的乳乌。

閱讀的樂趣:透過程序員認(rèn)識作者

即便每個(gè)人的寫作模式多半受到他人的影響,程序通常還是會(huì)融合多種風(fēng)格市咆,而成為自己獨(dú)有的特色汉操,如果你知道作者程序設(shè)計(jì)的偏好,閱讀他的程序就更得心應(yīng)手蒙兰。

閱讀程序時(shí)磷瘤,多半會(huì)采取由上而下,抽絲剝繭的方式搜变。透過記錄層層展開的樹狀結(jié)構(gòu)采缚,程序員可以逐步地建立起對系統(tǒng)的架構(gòu)觀,而且可以依照需要的粒度(粒度) 痹雅,決定展開的層次及精致程度仰担。

建立架構(gòu)觀點(diǎn)的認(rèn)識是最重要的事情糊识。雖然這一系列的文章前提為“閱讀他人的程序” 绩社,但我們真正想做的工作摔蓝,并不在于徹底地詳讀每一行程序員的細(xì)節(jié),而是想要透過重點(diǎn)式的程序“摘讀” 愉耙,達(dá)到對系統(tǒng)所需程度的了解贮尉。每個(gè)人在閱讀程序員的動(dòng)機(jī)不盡相同,需要了解的程度也就有深淺的分別朴沿。只有極為少數(shù)的情況下猜谚,你才會(huì)需要細(xì)讀每一行程序。

閱讀程序是新時(shí)代程序員必備的重要技能

本文至此已近尾聲赌渣,回顧曾探討的主題魏铅,我們首先研究了閱讀程序的動(dòng)機(jī)。尤其在開放源代碼的風(fēng)氣如此之盛的情況下坚芜,妥善利用開放源代碼所提供的資源览芳,不僅能夠更快學(xué)習(xí)到新的技術(shù),同時(shí)在源代碼版權(quán)合適時(shí)鸿竖,還可以直接利用現(xiàn)成的程序沧竟,大幅地提高開發(fā)階段的生產(chǎn)力。所以缚忧,閱讀程序儼然成為了新時(shí)代程序員必備的重要技能之一悟泵。

接著,我們提到了閱讀程序前的必要準(zhǔn)備闪水,包括了對編程語言糕非,命名慣例的了解等等。在此之后球榆,我們反覆提起了“由上而下”的閱讀方向的重要性峰弹。
由上而下的閱讀方式,是因?yàn)槲覀冎匾暭軜?gòu)更勝于細(xì)節(jié)芜果。從最外層的架構(gòu)逐一向內(nèi)探索鞠呈,每往內(nèi)探索一層,我們了解系統(tǒng)的粒度就增加了一個(gè)等級右钾。當(dāng)你識別出系統(tǒng)所用的架構(gòu)時(shí)蚁吝,便能夠輕易了解在這個(gè)架構(gòu)下會(huì)有的角色,以及它們之間的動(dòng)態(tài)及靜態(tài)的關(guān)系舀射。如此一來窘茁,許多資訊便不言可喻,毋需額外花費(fèi)力氣脆烟,便能夠快速理解山林。

好的名稱能夠摘要性地指出實(shí)例的作用

追蹤源代碼時(shí),固然可以用本來的方式邢羔,利用編輯器開啟所需的檔案驼抹,然后利用編輯器提供的機(jī)制閱讀桑孩,但是倘若能夠善用工具,閱讀程序員的效率及品質(zhì)都能大大提升框冀。在本文中流椒,我們介紹了一些工具,或許你還可以在坊間找到其他更有用的工具明也。

我在這一系列的文章中宣虾,實(shí)際帶著大家閱讀,追蹤了一個(gè)名為ml_pod的開放源代碼項(xiàng)目温数。它是一個(gè)AOL的Winamp的iPod的外掛程序绣硝。在追蹤的過程中,我們試著印證這一系列文中所提到的觀念及方法撑刺。我們采用逐漸開展的樹狀結(jié)構(gòu)來記錄追蹤的過程域那,并借以建立起對系統(tǒng)的概觀認(rèn)識。

就源代碼的閱讀來說猜煮,之前的討論涉及了工具面及技巧面次员。但還有一些主題不在這兩個(gè)范疇之內(nèi),例如王带,善用名稱賦予你的提示淑蔚。名稱做為隱喻(隱喻)的作用很大,好的名稱能夠摘要性地點(diǎn)出實(shí)體的作用愕撰,例如我們看到autoDetectIpod()刹衫,自然而然能夠想像它的作用在于自動(dòng)(自動(dòng))偵測(檢測)的iPod的存在。

我們在展開樹狀結(jié)構(gòu)時(shí)搞挣,有時(shí)候需要預(yù)看一層带迟,有時(shí)卻不需要這么做,便可得到印證囱桨。程序員都會(huì)有慣用的名稱以及組合名稱的方法仓犬,倘若能夠從名稱上理解,便毋需鉆進(jìn)細(xì)節(jié)舍肠,可以省去相當(dāng)多的時(shí)間搀继。例如,當(dāng)我們看到parseIpodDb ( )時(shí)翠语,便可以輕易了解它是剖析(解析)的iPod的資料庫( DB )的叽躯,因此便不需要立即鉆進(jìn)parseIpodDb ( )中查看底細(xì)。

盡管如此肌括,能否理解程序命名的用意点骑,和自身的經(jīng)驗(yàn)以及是否了解原作者的文化背景,是息息相關(guān)的。

命名本身就是一種文化產(chǎn)物黑滴。不同的程序員文化憨募,就會(huì)衍生出不同的命名文化。當(dāng)你自己的經(jīng)驗(yàn)豐富跷跪,看過及接觸過的程序員也多時(shí)馋嗜,對于名稱的感受及聯(lián)想的能力自然會(huì)有不同齐板。

這種感受和聯(lián)想的能力吵瞻,究竟應(yīng)該如何精進(jìn),很難具體描述甘磨。就我個(gè)人的經(jīng)驗(yàn)橡羞,多觀察不同命名體系的差異,并且嘗試歸納彼此之間的異同济舆,有助于更快地提升對名稱的感受及聯(lián)想力卿泽。

轉(zhuǎn)換立場,理解作者的思考方式

除了工具及技巧之外滋觉, “想要閱讀程序签夭,得先試著閱讀寫這個(gè)程序的程序員的心。 ”這句話說來十分抽象椎侠,或許也令人難以理解第租。

當(dāng)你在閱讀一段程序員時(shí),或許可以試著轉(zhuǎn)換自己的立場我纪,從旁觀者的角度轉(zhuǎn)換成為寫作者的心態(tài)慎宾,揣摩原作者的心理及處境。當(dāng)你試著設(shè)身處地站在他的立場浅悉,透過他的思考方式來閱讀趟据,追蹤他所寫下的程序員,將會(huì)感覺更加流暢术健。

許多軟件項(xiàng)目汹碱,都不是由一個(gè)程序員所獨(dú)力完成。因此荞估,在這樣的項(xiàng)目中比被,便有可能呈現(xiàn)多種不同的風(fēng)格。

許多項(xiàng)目會(huì)由架構(gòu)師決定主體的架構(gòu)及運(yùn)作泼舱,有既定實(shí)施的命名慣例等缀,及程序設(shè)計(jì)需要遵守方針。在多人開發(fā)的模式下娇昙,越是好的軟件項(xiàng)目尺迂,越看不出某程序片段究竟是由誰所寫下的。

不過,有些開放源代碼的項(xiàng)目噪裕,往往又整合了其他開放源代碼的項(xiàng)目蹲盘。有的時(shí)候,也很難求風(fēng)格的統(tǒng)一膳音,便會(huì)出現(xiàn)混雜的情況召衔。好比之前提到的ml_pod項(xiàng)目,因?yàn)槌绦蛑谢旌狭瞬煌膩碓醇老荩尸F(xiàn)風(fēng)格不一致的情況苍凛。

我在閱讀非自己所寫的程序時(shí),會(huì)觀察原作者寫作的習(xí)慣兵志,借以對應(yīng)到腦中所記憶的多種寫作模型醇蝴。在閱讀的過程中,讀完幾行程序想罕,我會(huì)試著猜想原作者在寫下這段程序時(shí)的心境悠栓。他寫下這段程序的用意是什么?為什么他會(huì)采取這樣的寫法按价?順著原作者的思考理路閱讀惭适,自己的思考才能更貼近對方寫作當(dāng)時(shí)的想法。

當(dāng)你短暫化身為原作者時(shí)楼镐,才能更輕易的理解他所寫下的程序癞志。 如果你能知道原作者的背景,程序設(shè)計(jì)時(shí)的偏好鸠蚪,閱讀他的程序今阳,就更能得心應(yīng)手了。

從程序員著手認(rèn)識作者獨(dú)有的風(fēng)格茅信,進(jìn)而見賢思齊

我在閱讀別人寫下的程序時(shí)盾舌,我會(huì)試著猜想,原作者究竟是屬于那一種“流派”呢蘸鲸?每個(gè)人都有自己獨(dú)特的寫作模式妖谴,即便每個(gè)人的寫作模式多半受到他人的影響─ ─不論是書籍的作者,學(xué)習(xí)過程中的指導(dǎo)者酌摇,或一同參與項(xiàng)目的同儕膝舅,但每個(gè)程序員通常會(huì)融合多種風(fēng)格,而成為自己獨(dú)有的風(fēng)格窑多。

面向?qū)ο蟮幕窘塘x派仍稀,總是會(huì)以他心中覺得最優(yōu)雅的面向?qū)ο蠓绞絹碜珜懗绦颉6喿x慣用埂息,善用設(shè)計(jì)模式的程序員所寫下的程序時(shí)技潘,不難推想出他會(huì)在各種常見的應(yīng)用情境下遥巴,套用哪些模式。

有些時(shí)候享幽,在閱讀之初铲掐,你并不知道原作者的習(xí)性跟喜好,甚至你也不知道他的功力值桩。但是摆霉,在閱讀之后,你會(huì)慢慢地從一個(gè)程序員所寫下的程序奔坟,開始認(rèn)識他携栋。

你或許會(huì)在閱讀他人的程序時(shí),發(fā)現(xiàn)令人拍案叫絕的技巧或設(shè)計(jì)蛀蜜。你也有可能在閱讀的同時(shí)刻两,發(fā)現(xiàn)原作者所留下的缺失或?qū)懽鲿r(shí)的缺點(diǎn)增蹭,而暗自警惕于心滴某。這也算是閱讀他人程序時(shí)的一項(xiàng)樂趣。

當(dāng)你從視閱讀他人的程序?yàn)槲吠咀搪酰D(zhuǎn)變成為可以從中獲取樂趣的時(shí)候霎奢,我想,你又進(jìn)到了另一個(gè)境界饼灿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幕侠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碍彭,更是在濱河造成了極大的恐慌晤硕,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庇忌,死亡現(xiàn)場離奇詭異舞箍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)皆疹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門疏橄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人略就,你說我怎么就攤上這事捎迫。” “怎么了表牢?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵窄绒,是天一觀的道長。 經(jīng)常有香客問我崔兴,道長彰导,這世上最難降的妖魔是什么浊闪? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮螺戳,結(jié)果婚禮上搁宾,老公的妹妹穿的比我還像新娘。我一直安慰自己倔幼,他們只是感情好盖腿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著损同,像睡著了一般翩腐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上膏燃,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天茂卦,我揣著相機(jī)與錄音,去河邊找鬼组哩。 笑死等龙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伶贰。 我是一名探鬼主播蛛砰,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼黍衙!你這毒婦竟也來了泥畅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤琅翻,失蹤者是張志新(化名)和其女友劉穎位仁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體方椎,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聂抢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辩尊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涛浙。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖摄欲,靈堂內(nèi)的尸體忽然破棺而出轿亮,到底是詐尸還是另有隱情,我是刑警寧澤胸墙,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布我注,位于F島的核電站,受9級特大地震影響迟隅,放射性物質(zhì)發(fā)生泄漏但骨。R本人自食惡果不足惜励七,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奔缠。 院中可真熱鬧掠抬,春花似錦、人聲如沸校哎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闷哆。三九已至腰奋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抱怔,已是汗流浹背劣坊。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屈留,地道東北人局冰。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像绕沈,于是被迫代替她去往敵國和親锐想。 傳聞我的和親對象是個(gè)殘疾皇子帮寻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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