閱讀原始碼的方法論
隨著網際網路行業的發展,優秀的開源框架越來越多,我們可以輕易地在 Github 上找到業界頂尖的大佬親手寫的程式碼,對於這種放在眼前的美食我們怎麼能視而不見呢?
但實際上,原始碼一般比較複雜,一個框架動輒上萬行、幾百個類,互相之間又有著各種各樣奇奇怪怪的聯絡。想要從這一堆複雜冗長的程式碼中理清楚頭緒實在是非常困難。下面這篇文章就總結了我在閱讀原始碼時的一些方法與技巧,希望可以幫到大家。
下面的框架我會按照 Android 中的圖片載入框架 Glide 為案例來進行講解。
此外如果大家有興趣可以看看我專門針對Glide 原始碼解讀的文章:
https://www.jianshu.com/p/9bb50924d42a自頂向下的分析
在拿到一份原始碼時(假設你已經學會如何使用這個框架),我們第一件要做的事情是思考如果讓我們來設計這個框架,我們會怎樣設計,應該分成哪幾個模組,模組之間如何耦合,如何讓使用者使用起來很簡單的同時又可以擴充套件自己的功能等等。
當我們仔細分析一波後,會逐漸明白這個框架的設計難點、關鍵節點、核心等等。例如要我們設計一個載入圖片的框架,那第一個想到的肯定就是快取(記憶體快取、磁碟快取等等)、載入源(HTTP、File、Resource 等等)、格式轉換等等這些要點,然後我們帶著這些問題去看框架,效率自然就高了很多。
用巨集觀角度去分析程式碼細節,自頂向下縷清關係。
模組劃分
用模組化思維分析。
其實通過上面的思考,我們已經能大概的給這個框架分出幾個模組了,例如:快取模組、載入模組、圖片處理模組等等。
然後我們開始看程式碼,一個優秀的框架都會有很清晰的模組劃分,我們先根據模組來看,因為包是按照模組劃分的,所以可以根據分包來了解框架中的模組,下面看一下 Glide 框架原始碼的包劃分:

分包結構
第一個 load 包肯定是載入相關的東西,例如圖片請求的執行、資料解碼。
request 包應該是請求封裝模組,我們發起一個請求時應該會通過這個包下面的類進行包裝。
signature 叫簽名,大概是關於請求標識、資源標識相關的?我們可以先這麼理解。
util 是工具包,放一些全域性共用的工具類。
其它的可以自己理解。到了這裡我們已經能對這個框架有個粗淺的認識了。
另外,要相對模組劃分有更深的瞭解,我們光看這個還是不行的,需要看一些程式碼才能更深入的瞭解,例如根據我們平時使用的方式,來看整個圖片載入的流程是怎樣的,每個流程負責什麼任務,這樣可以加深對模組的認識。
下面我們就可以按照模組來學習原始碼了,例如先學習 request 包下面的程式碼,明白請求是如何建立的等等,閱讀原始碼時一定要 時刻保持著清醒的頭腦 ,千萬不可迷失在層層的巢狀呼叫關係中。
有一點需要注意: 千萬不可急於求成,看不明白的就放在後面看,先看能看明白的。
流程分析
瞭解一套圖片載入的請求流程比較重要,我們通過分析這些流程能明白每個模組之間的關係。
如果看過一些程式碼已經知道,模組之間都是使用介面耦合,每個介面又有很多實現類,具體的實現類要在程式碼執行時才能知道,所以想要找到一個方法具體的實現也是一件比較麻煩的事情。除了通過除錯可以很方便的看到呼叫流程之外我這裡再給一個技巧: 關鍵點列印方法呼叫棧 。
列印方法呼叫棧的程式碼如下:
StringBuilder traceBuilder = new StringBuilder(); for(StackTraceElement e : Thread.currentThread().getStackTrace()){ traceBuilder.append(e.toString()); traceBuilder.append("\n"); } Log.d(TAG, traceBuilder.toString());
搞懂流程之後可以畫一個流程圖出來,例如下面這樣:

載入流程
當然了想要畫出這樣的流程圖是需要時間的, 不是很輕易的就能完成,需要對原始碼有了一定的瞭解之後才行。
類分析
類分析是指我們在實際閱讀原始碼時針對同一個家族的類的分析。
類與類之間肯定會有這很多複雜的聯絡,我們在閱讀時想要理清楚可以藉助一些工具,例如自動生成 UML 類圖的外掛。
效果如下:

UML 圖
這裡用的是 Android Studio 中的 simpleUML 外掛來生成的,直接搜尋安裝即可。
有了這種工具我們的效率將會事半功倍。
其實閱讀原始碼最重要的技巧就是:死磕。沒有什麼特別的方法可以讓你在很快的時間內對一個框架了如指掌,想要學好必須多花點時間仔細閱讀,看得多了,自然就一回生二回熟了。
如果覺得還不錯的話,歡迎關注我的公眾號,我會不定期發一些乾貨~

公眾號
也可以加我微信:

個人微信