如何正確的閱讀源代碼?
寫完「你也可以像 Prisma 一樣渲染圖像」之后,有讀者提了這樣一個問題:
我猜您平時應該有閱讀開源項目的源碼,好的開源軟件或者框架,動輒數萬行的源碼,雖說是寶藏,但我看源碼一直不得要領,投入時間不少但收獲甚微,請教下:
您閱讀源碼的關注點一般有哪些?
您看源碼有沒有什么方法論呢,如何抓住重點下手?有時面對優秀的開源框架,想學習,我甚至都不知從哪看起。
關于這個問題,我說兩句。
閱讀優秀的源代碼是軟件工程師提高自己編程能力和學習開源框架的最佳手段之一。作為一名運動員,除了持續的刻意練習,還需要觀摩大量對手的比賽視頻。作為一名小說家,除了筆耕不輟,還需要閱讀大量的其他作家的偉大作品。當然,觀摩和閱讀不是目的,是手段。路遙在創作《平凡的世界》之前讀了大量的「名著」,然后,他把所有尊敬的作家都安放在遠方歷史為他們準備的「先圣詞」中,讓他們各自光芒四射,照耀大地,然后開始創作百萬巨著《平凡的世界》。照耀你的世界的光芒,應該是自己發出的。
程序員亦是如此。在編程的路上,有無數的大師寫出了偉大的代碼和軟件,去學習他們的編程技巧和技術風格,取其精華,去其糟粕,最后完成自己的作品。2005年左右我有幸參與了一個類似 CORBA 的分布式應用系統的開發,我在那段時間差不多通讀了這個項目的早期代碼,其整體架構規劃和代碼設計的精巧程度讓人嘆為觀止(代碼的編寫者是早期的 CORBA 規范制定者)。這個經歷對我后來的編程之路產生了深遠的影響。
與編程一樣,閱讀別人的源代碼永遠不是一件輕松的事,或者說,是一件困難的事情,需要持續的投入,閱讀、研究、把玩、實踐。很多人覺得拿到了源代碼就像買了本書一樣,放到書柜上,立刻就產生了一種學會了的錯覺(我就是這樣,微笑),但真正實踐起來才會體驗到強烈的挫敗感。大部分情況下,讀不下去,不是方法不好,而是投入度不夠。
閱讀源代碼,一定要找到好的開源項目。什么是好的項目?口碑好且應用廣泛的項目就是好項目,比如 Docker、Spring、OpenResty,都是非常好的閱讀素材。另外,完善的文檔和足夠的 test case 覆蓋率,都是衡量一個開源項目是否優秀的標準。很多人說,代碼即文檔,好的代碼本身就是自解釋的。但是,對于規模宏大的開源軟件來說,沒有文檔是不可想象的。所以在閱讀源代碼之前,一定要讀文檔。盡管讀了文檔之后,你可能不知道代碼的技術細節,但至少可以了解項目的輪廓。結合開源項目的代碼目錄,差不多可以繪制出一個粗粒度的整體架構圖,類似這樣的:
然后為每個目錄(或模塊)做記錄和標識,逐一閱讀,或者直接去讀你最感興趣的部分。
我讀源代碼喜歡自頂向下的方式,先把整體脈絡理清楚,然后按照模塊去閱讀代碼,把類和類、函數和函數之間的調用關系記錄下來,如果可以進行逆向工程,用類似 Intelli IDEA 這樣的工具把代碼之間的調用關系用 Diagrams 展現出來,閱讀會更加直觀一些,不同的語言有不同的工具可以選擇。
另外,閱讀 test case 同樣能幫助你理解作者的代碼設計意圖。正常情況下,測試用例都是從文檔和設計衍生出來的,而不是完成了代碼再寫 test case。閱讀測試用例,可以讓你更清晰的知道對應的類和函數想要做什么事情。
閱讀源代碼需要順手的工具,我自己喜歡用 Vim,配合 NERDTree、CtrlP、ctags、taglist 等插件,Vim 可以成為一款優秀的代碼瀏覽工具,而且非常輕量級。你可以在終端里用命令迅速打開、關閉、查找和索引程序,并進行有效的關聯跳轉(靜態代碼)。如果你不習慣,也可以用 Sublime Text,Atom 等工具。當然,如果你要進行調試和跟蹤,那最好使用相關程序棧的 IDE 工具,比如 Eclipse、Jet Brain 系列工具,Xcode 等等,這樣你可以在 debug 狀態跟蹤所有的函數調用和變量參數在執行時間線上的變化。
如果你喜歡 Vim,可以看下這篇「Vim 8.0,姍姍來遲」。
重復一句,工具和方法永遠不是最重要的,去讀,并在遇到困難的時候,看不明白的時候,咬牙堅持下去,抽絲剝繭,逐個擊破。最終,你會在冰冷黑暗的二進制世界里面看到一張地圖,找到一座燈塔,然后去解釋和還原這個底層世界里每一個細微方面的語義,重建出高層次的抽象概念和關系。
最后推薦兩本書,《Docker 源碼分析》和《Go 語言學習筆記》,這兩本書,都是關于 Go 語言的,可以說是源代碼閱讀的典范,有興趣可以找來讀讀。
來自:http://www.jointforce.com/jfperiodical/article/3328