學習開源專案,不能選擇性眼瞎

四猿外發表於2021-08-04

最近奧運會,中國還是依然 NB,尤其前兩天的男子百米半決賽、決賽,徹底被蘇神點燃了。

說是亞洲奇蹟,一點也不為過。

看比賽,有好的,也有氣人的,比如裁判,裁判適當照顧東道主也能忍了,但是有時候太過分了,直接選擇性眼瞎。

說到選擇性眼瞎,我想的一個事情。

我們們幹程式設計師的,經常需要應用、研究一些開源元件。研究開源元件,就少不了去看資料、看原始碼。在看程式碼、學習的過程中,我們們可不能像那些眼瞎的裁判,我們們需要高效的學習:看清全域性、主要脈絡、關鍵細節。

這篇文章就和大家說說我自己高效學習的方法。

對我而言,做好這件事的關鍵就在於問自己七個問題。

問題1. 元件解決了什麼問題

問這個問題的目的是明確元件的問題域,任何元件的出現都是為了解決某類問題的。

我們在職業生涯裡,遇到的技術問題其實是有限的。面對這些有限的問題,我們熟悉的元件越多,解決問題的思路和辦法就越多。當你對某種技術問題,有著比別人更多的思路和辦法,那自然而然,你的技術話語權就會越大。

以我曾經深入研究過的 druid(阿里的開源資料庫連線池)元件為例:

druid 要解決的問題本質其實是如何降低應用和中介軟體互動所消耗的時間成本。

知道了 druid 要解決的問題,我們就等於知道了它的核心主題。druid 的主要技術思路,全部都是圍繞著這個核心主題來實現的。

比如,druid 本身的 LRU 策略、對一些關鍵物件的快取、競爭資源的高效率利用……都是圍繞著這個核心問題來設計和落地的。

同時,我們明確了 druid 要解決的問題後,如果我們對現在 jedis 這套東西不滿意,是不是就可以利用 druid 的技術思路,重新設計和實現一套新元件,去替代 jedis,以便降低和 redis 互動的時間成本呢?

問題2. 元件有什麼優點

確認了元件需要解決的問題,只是第一步。一套開源元件,往往專案都比較龐大。所以,就得想個辦法分而克之,分出各個具體的知識點去學習。

而這些知識點,往往和官方文件宣傳的元件優點可以對上。

比如,druid 的官方文件是這麼說的:

從上面這幅圖,就可以看出來,druid 有如下幾個特點:

  1. 能被監控
  2. 容易擴充套件
  3. 效能優秀
  4. 穩定性好
  5. 安全
  6. 執行期問題容易排查

這些就是我們要去學習的各個知識點。

問題3. 元件的主幹和分支都是哪些

知道了元件的優點,就等同於知道了需要學習的知識點。可是,知識點如果多而雜,就需要確認好哪些學哪些不學?哪些先學哪些後學?

那麼,元件的主幹和分支就需要分解出來,以便定出學習計劃。而劃分出主幹和分支,就需要綜合我們前面說的元件要解決的問題。

通過前面的學習,我們知道 druid 解決的是降低中介軟體的時間成本,也知道了它的特點:

  1. 能被監控
  2. 容易擴充套件
  3. 效能優秀
  4. 穩定性好
  5. 安全
  6. 執行期問題容易排查

此時,我們的學習計劃就是:先學習 druid 是如何實現高效能的;高效能後,如果我們研究 druid 是為了後續在工作中應用,那麼,能被監控這個特點就是下一個要學習的知識點。

所以,這一問,是為了擬定學習計劃而問。

問題4. 元件的這些優點是如何實現的

在上個問題之後,我們就可以分步驟的進行學習了。學的怎麼樣,就需要通過這個問題,來考察自己是否真的學懂了這些知識點。

回到 druid 上,讓人滿意的答案就是,我們能用自己的話去總結出每個知識點的技術實現。比如:

問:druid 的監控是如何實現的?

答:druid 通過自己實現 JDBC API 自身提供的 PooledConnection、Connection、Statement、ResultSet介面,獲得了可以在這些介面的關鍵方法中植入統計的能力。統計的資料會定期取樣後儲存在某些命名叫做 xxxStat 的物件裡,供後面展示使用。

問:druid 是如何實現擴充套件的?

答:能擴充套件的實現方式是第三方實現 druid 提供的一個 Filter 介面後,再被配置到 druid 的配置檔案裡。這樣就會在 DruidDataSource 初始化的時候,去讀取並初始化這些實現了 Filter 介面的例項。初始化後的 Filter 會在後面 druid 從建立資料庫連線到執行 SQL 語句再到釋放連線這一系列步驟後,被不斷的鏈式執行。

就這樣,分知識點回答出讓自己滿意的答案,就等同於考核了自己對每個知識點學習的質量,如果回答不滿意,就再去查漏補缺即可。

問題5. 元件的系統設計思路是什麼

我們學習了各個零散的知識點之後並不夠,因為學習一套開源元件,原理是基礎,系統設計則是骨架。

明白了技術點,只是對當編碼高手有用,但是當你自己設計元件的時候,你的底氣在哪裡呢?答案就在這些你看過的開源元件的系統設計思路上。

所以,把知識點融合起來形成一個整體,再去推斷出系統的設計思路,對我們成為一名優秀的架構師,是有非常大的幫助的。

比如,通過各個知識點的深入學習,融會貫通後,我認為 druid 的設計思路如下:

如果以後遇到為公司底層構造一套池化中介軟體物件的需求時,這種設計思路自然就成了我設計的重要模板之一。

問題6. 元件的缺點是什麼

為什麼會問元件的缺點?因為在我如此瞭解了一套元件之後,卻還是免不了誤用和踩坑,這其中最嚴重的就是,生產環境在元件出現問題之後,我們卻沒有緊急預案。

這種現象的原因就是沒有去深入思考過一套技術的利弊。問元件的缺點,就會迫使我們去深入思考利弊,從而在以後不管是應用元件,又或者是去根據學習到的知識自己實踐,都能成竹在胸,從容以對。

回到 druid 身上,當我們去讀它原始碼的時候,思考一下:

durid 的這些實現真的就是完美的嗎?

那肯定不是, 比如:

  • druid 的取樣功能很多時候我們並不需要,但是由於 druid 的實現是寫死在實現的關鍵程式碼裡的,所以無法自由的對其進行插拔。這時候,就要注意,取樣可能造成的記憶體佔用問題。

  • druid 是對 JDBC API 做了層層封裝的,在這些封裝中 druid 又新增了很多自己的實現。但是,這些實現很難避免bug,然而由於有這些封裝,就會導致 Bug 很難查,又或者很難自己改。這時候,就需要在測試環境,把 druid 的日誌級別調成 DEBUG 級別,然後仔細觀察日誌,看看是否有什麼不可知的風險。

所以,這一問,是為了深度思考,讓我們在任何新技術的學習和實戰時,都能成為最穩定的那個仔。

不管以後我們模仿還是應用 druid,就能提前預測到風險,從而重點監控,提前準備預案。

問題7. 和同類別的元件之間有什麼區別

當學習完了元件,知道了元件的優缺點,理解了元件的執行原理,明白了元件的設計思路之後,一切就完整了嗎?

對不起,還不夠。

因為我們還缺乏一種東西,就是學習的擴充,即學習的廣度。

學習元件,我們除了知道它要解決的問題域外,還需要知道它在同類元件中的地位。

為什麼?因為以後我們去任何一個稍微成規模的公司後,需要面臨一個問題,內部的競爭。

比如,我們寫了一套訊息治理中介軟體。如果想提升自己的技術話語權,就需要在全公司,和同類產品競爭。競爭勝出了,自己的職業生涯就有了巨大發展的可能。

回到 druid 上,在SpringBoot2.0時代,druid 出現了巨大的競爭對手——HiKariCP。

而 HiKariCP 之所以能勝出,是因為它排除了 druid 使用的公平鎖,使得效能提升了大約 70%

通過 druid 和 HiKariCP 的比較和學習,我們就能更加深入的理解高併發,能更有效率的去壓榨出系統的效能。

通過 druid 和 HiKariCP 作者之間的互相較量,我們還能明白如何去更好的對比競品,去展現最為關鍵的資料指標,一舉贏得勝利。

以上列舉的七個問題,是我為了解決高效高質研究開源元件,得到的最佳實踐。

總結一下:

  • 先通過問元件解決了什麼問題,去確定自己的學習目的和思考邊界。
  • 再問元件有什麼優點,以及主幹和分支是哪些,去擬定出學習計劃。
  • 再後,通過問元件的優點是如何實現的,去考察自己的學習質量。
  • 然後,通過問元件的系統設計思路是什麼,讓自己講學到的各種獨立的知識融匯貫通,打造成體系。
  • 最後,通過問元件的缺點是什麼以及和競品的區別去迫使自己在學習之外,再行深度思考和廣度思考,對學習進行查漏補缺以及進一步提升學習質量,打造出更為突出的知識體系。

IT這行業是需要不斷學習的,而高效高質量學習,是讓我們的職業生涯走的更穩更順的關鍵所在。


你好,我是四猿外。

一家上市公司的技術總監,管理的技術團隊一百餘人。

我從一名非計算機專業的畢業生,轉行到程式設計師,一路打拼,一路成長。

我會把自己的成長故事寫成文章,把枯燥的技術文章寫成故事。

歡迎關注我的公眾號,關注後可以領取高併發、演算法學習資料。

相關文章