即便每個人的寫作模式多半受到他人的影響,程式人通常還是會融合多種風格,而成為自己獨有的特色,如果你知道作者程式設計的偏好,閱讀他的程式碼就更得心應手。
閱讀程式碼時,多半會採取由上而下、抽絲剝繭的方式。透過記錄層層展開的樹狀結構,程式人可以逐步地建立起對系統的架構觀,而且可以依照需要的粒度(Granularity),決定展開的層次及精緻程度。
建立架構觀點的認識是最重要的事情。雖然這一系列的文章前提為「閱讀他人的程式碼」,但我們真正想做的工作,並不在於徹底地詳讀每一行程式碼的細節,而是想要透過重點式的程式碼「摘讀」,達到對系統所需程度的瞭解。每個人在閱讀程式碼的動機不盡相同,需要了解的程度也就有深淺的分別。只有極為少數的情況下,你才會需要細讀每一行程式碼。
###閱讀程式碼是新時代程式人必備的重要技能 這一系列的文章至此已近尾聲,回顧曾探討的主題,我們首先研究了閱讀程式碼的動機。尤其在開放原始碼的風氣如此之盛的情況下,妥善利用開放原始碼所提供的資源,不僅能夠更快學習到新的技術,同時在原始碼版權合適時,還可以直接利用現成的程式碼,大幅地提高開發階段的生產力。所以,閱讀程式碼儼然成為了新時代程式人必備的重要技能之一。
接著,我們提到了閱讀程式碼前的必要準備,包括了對程式語言、命名慣例的瞭解等等。在此之後,我們反覆提起了「由上而下」的閱讀方向的重要性。
由上而下的閱讀方式,是因為我們重視架構更勝於細節。從最外層的架構逐一向內探索,每往內探索一層,我們瞭解系統的粒度就增加了一個等級。當你識別出系統所用的架構時,便能夠輕易瞭解在這個架構下會有的角色,以及它們之間的動態及靜態的關係。如此一來,許多資訊便不言可喻,毋需額外花費力氣,便能夠快速理解。
###好的名稱能夠摘要性地點出實體的作用 追蹤原始碼時,固然可以用本來的方式,利用編輯器開啟所需的檔案,然後利用編輯器提供的機制閱讀,但是倘若能夠善用工具,閱讀程式碼的效率及品質都能大大提升。在本系列文章中,我們介紹了一些工具,或許你還可以在坊間找到其他更有用的工具。
我在這一系列的文章中,實際帶著大家閱讀、追蹤了一個名為ml_pod的開放原始碼專案。它是一個Winamp的iPod plug-in程式。在追蹤的過程中,我們試著印證這一系列文中所提到的觀念及方法。我們採用逐漸開展的樹狀結構來記錄追蹤的過程,並藉以建立起對系統的概觀認識。
就原始碼的閱讀來說,之前的討論涉及了工具面及技巧面。但還有一些主題不在這兩個範疇之內,例如,善用名稱賦予你的提示。名稱做為隱喻(Metaphor)的作用很大,好的名稱能夠摘要性地點出實體的作用,例如我們看到autoDetectIpod(),自然而然能夠想像它的作用在於自動(Auto)偵測(Detect)iPod的存在。
我們在展開樹狀結構時,有時候需要預看一層,有時卻不需要這麼做,便可得到印證。程式人都會有慣用的名稱以及組合名稱的方法,倘若能夠從名稱上理解,便毋需鑽進細節,可以省去相當多的時間。例如,當我們看到parseIpodDb()時,便可以輕易瞭解它是剖析(Parse)iPod的資料庫(DB),因此便不需要立即鑽進parseIpodDb()中查看底細。
儘管如此,能否理解程式人命名的用意,和自身的經驗以及是否瞭解原作者的文化背景,是息息相關的。
命名本身就是一種文化產物。不同的程式人文化,就會衍生出不同的命名文化。當你自己的經驗豐富,看過及接觸過的程式碼也多時,對於名稱的感受及聯想的能力自然會有不同。
這種感受和聯想的能力,究竟應該如何精進,很難具體描述。就我個人的經驗,多觀察不同命名體系的差異,並且嘗試歸納彼此之間的異同,有助於更快地提升對名稱的感受及聯想力。
###轉換立場,理解作者的思考方式 除了工具及技巧之外,「想要閱讀程式碼,得先試著閱讀寫這個程式碼的程式人的心。」這句話說來十分抽象,或許也令人難以理解。
當你在閱讀一段程式碼時,或許可以試著轉換自己的立場,從旁觀者的角度轉換成為寫作者的心態,揣摩原作者的心理及處境。當你試著設身處地站在他的立場,透過他的思考方式來閱讀、追蹤他所寫下的程式碼,將會感覺更加流暢。
許多軟體專案,都不是由單一程式人所獨力完成。因此,在這樣的專案中,便有可能呈現多種不同的風格。
許多專案會由架構師決定主體的架構及運作,有既定實施的命名慣例,及程式設計需要遵守方針。在多人開發的模式下,越是好的軟體專案,越看不出某程式碼片段究竟是由誰所寫下的。
不過,有些開放原始碼的專案,往往又整合了其他開放原始碼的專案。有的時候,也很難求風格的統一,便會出現混雜的情況。好比之前提到的ml_pod專案,因為程式碼中混合了不同的來源,而呈現風格不一致的情況。
我在閱讀非自己所寫的程式碼時,會觀察原作者寫作的習慣,藉以對應到腦中所記憶的多種寫作模型。在閱讀的過程中,讀完幾行程式碼,我會試著猜想原作者在寫下這段程式碼時的心境。他寫下這段程式碼的用意是什麼?為什麼他會採取這樣的寫法?順著原作者的思考理路閱讀,自己的思考才能更貼近對方寫作當時的想法。
當你短暫化身為原作者時,才能更輕易的理解他所寫下的程式碼。 如果你能知道原作者的背景,程式設計時的偏好,閱讀他的程式碼,就更能得心應手了。
###從程式碼著手認識作者獨有的風格,進而見賢思齊 我在閱讀別人寫下的程式碼時,我會試著猜想,原作者究竟是屬於那一種「流派」呢?每個人都有自己獨特的寫作模式,即便每個人的寫作模式多半受到他人的影響──不論是書籍的作者、學習過程中的指導者,或一同參與專案的同儕,但每個程式人通常會融合多種風格,而成為自己獨有的風格。
物件導向的基本教義派,總是會以他心中覺得最優雅的物件導向方式來撰寫程式。而閱讀慣用、善用設計模式的程式人所寫下的程式碼時,不難推想出他會在各種常見的應用情境下,套用哪些模式。 有些時候,在閱讀之初,你並不知道原作者的習性跟喜好,甚至你也不知道他的功力。但是,在閱讀之後,你會慢慢地從一個程式人所寫下的程式碼,開始認識他。
你或許會在閱讀他人的程式碼時,發現令人拍案叫絕的技巧或設計。你也有可能在閱讀的同時,發現原作者所留下的缺失或寫作時的缺點,而暗自警惕於心。這也算是閱讀他人程式碼時的一項樂趣。
當你從視閱讀他人的程式碼為畏途,轉變成為可以從中獲取樂趣的時候,我想,你又進到了另一個境界。