怎麼讀? 怎麼看別人的 Source code, 然後再去修改, 通常的回答, 大概是看 天份
.
- 我的做法通常是 先搞清楚此程式的
輸入、輸出
, 再從main()
等開始位置開始追, 經過追蹤、測試
來找到要改的地方.
這一系列文章是作者(王建興)將他閱讀程式碼的心得 與 優點寫出來, 建議有空可以看看(文章下面內容, 是我覺得的重點摘錄). 🙂
- 閱讀他人的程式碼(1)─讀懂程式碼,使心法皆為我所用
- 先了解系統架構與行為模式,再細讀
- 接觸他人的程式碼,大致上可以分為三種程度:
- 了解
- 修改、擴充
- 抽取、提煉。
- 了解別人的程式碼是最基礎的工作,倘若不能了解自己要處理的程式碼,就甭論修改或擴充,更不可能去蕪存菁,從中萃取出自己所需,回收再利用別人所撰寫的程式碼。
- 閱讀程式碼的重點,不在於讀完每一行程式碼,而是在於有效率地透過探索及閱讀,從而了解系統的架構及行為模式。以便在你需要了解任何片段的細節實作時,能夠很快在腦上對映到具體的程式碼位置,直到那一刻,才是細讀的時機。
- 閱讀他人的程式碼(2) 摸清架構,便可輕鬆掌握全貌
- 先試著捕捉系統架構性的觀念,不要過早鑽進細節,因為那通常對於你了解全貌,沒有多大的幫助。閱讀程式碼不需要從第一行讀起,我們的目的並不是在於讀遍每一段程式碼。
- 探索架構的第一件事:找出系統如何初始化
- 不論某個系統所採用的架構是否為大部分人所熟知的,在試著探索一個系統的長相時,我們應該找出來幾個答案,了解在它所用的架構下,下列這件事是如何被完成的:
- 系統如何初始化
- 與這個系統相接的其他系統(或使用者)有那些,而相接的介面又是什麼
- 系統如何反應各種事件
- 系統如何處理各種異常及錯誤。
- 閱讀他人的程式碼 (3) 優質工具在手,讀懂程式非難事
- gtags是GNU GLOBAL source code tag system,它不只搜尋文字層次,而且因為具備了各種語言的語法剖析器,所以在搜尋時,可以只針對和語言有關的元素,例如類別名稱、函式名稱等。
- 而且,它能針對原始碼的內容進行索引,這意謂一旦建好索引之後,每次搜尋的動作,都毋需重新讀取所有原始碼的內容並逐一搜尋。只需要以現成的索引結構為基礎,即可有效率的尋找關鍵段落。
- 閱讀他人的程式碼 (4)望文生義,進而推敲組件的作用
- 我喜歡將系統的運作情境,比擬成系統會上演的故事情節。在閱讀細節性質的程式碼前,先知道系統究竟會發生那些故事,是必備的基本功課。你可以利用熟悉或者自己發明的表示工具,描述你所找到的情境。甚至可以只利用簡單的列表,直接將它們列出。只要能夠達到記錄的目的,對程式碼閱讀來說,都能夠提供幫助。或者,你也可以利用UML中的類別圖、合作圖、循序圖之類的表示方法,做出更詳細的描述。
- 探索架構的第一步──找到程式的入口
- 系統多會採用相同的架構處理Plug-In程式
- 閱讀他人的程式碼(5)找到程式入口,再由上而下抽絲剝繭
- 展開的同時,隨手記錄樹狀結構
- 當我們從一個入口點找到三個分支後,可以順著每個分支再展開一層,所以分別繼續閱讀init、quit、以及PluginMessageProc的內容,並試著再展開一層。閱讀的同時,你可以在文件中試著記錄展開的樹狀結構。
- 範例:
- init():初始化動作
- itunesdb_init_cc():建立存取iTunes database的同步物件
- 初始化資料結構
- 初始化GUI元素
- 載入設定
- 建立log檔
- autoDetectIpod():偵測iPod插入的執行緒
- quit():終止化動作
- itunesdb_del_cc():終止存取iTunes database的同步物件
- 關閉log檔
- 終止化GUI元素
- PluginMessageProc():以訊息的方式處理程式所必須面臨的各種事件
- 執行所連接之iPod的MessageProc()
- 這部分必須要留意幾個重點。首先,應該一邊閱讀,一邊記錄文件。因為人的記憶力通常有限,對於陌生的事物更是容易遺忘,因此邊閱讀邊記錄,是很好的輔助。
- 閱讀他人的程式碼(6)閱讀的樂趣:透過程式碼認識作者
- 轉換立場,理解作者的思考方式
- 當你在閱讀一段程式碼時,或許可以試著轉換自己的立場,從旁觀者的角度轉換成為寫作者的心態,揣摩原作者的心理及處境。當你試著設身處地站在他的立場,透過他的思考方式來閱讀、追蹤他所寫下的程式碼,將會感覺更加流暢。