[譯] 如何心平氣和地閱讀程式碼

Leben_Ito發表於2019-03-28

[譯] 如何心平氣和地閱讀程式碼

  1. 多寫程式碼
  2. 多讀程式碼
  3. 每天都完成以上內容

這是我在兩年前轉向程式設計時給我自己的要求。幸運的是,現在有很多線上編寫程式碼的課程和教程可以教你寫程式碼,然而他們卻基本上都沒有去教你如何閱讀程式碼。

這是一個重要的區分點。隨著進入科技領域的程式設計訓練營畢業生數量的 飛速增長。強調閱讀原始碼變得更加重要。Brandon Bloom 寫道

如果它在 的機器上執行,它就是 的軟體。 應該對此負責,所以 必須對它瞭如指掌。

Yes, you.

雖然每個程式設計師都應該閱讀原始碼,但 事實 並非如此。許多程式設計師不願意閱讀原始碼是因為它閱讀起來很難,容易打擊他們的信心,並且讓他們感到自己很蠢。我知道,因為這就是我的感受。

其實只是方法不對

在我閱讀其他人的程式碼時,我想出了一個只需要三步的閱讀方法。可能有些人已經在遵循這些步驟,但我相信大部分人是沒有的。

我的步驟如下。

1. 選一個你感興趣的點

Image Source: [https://thenextweb.com/wp-content/blogs.dir/1/files/2010/04/twitter-location-300x200.jpg](https://thenextweb.com/wp-content/blogs.dir/1/files/2010/04/twitter-location-300x200.jpg)

回想我第一次閱讀原始碼的時候,那簡直是一場災難。

我當時正在學習 Sinatra,然後我想更好的瞭解底層執行機制。然而,我並不知道應該從哪裡開始讀,於是我找到了它在 Github 上的 repo 然後隨便開啟了一個檔案。不開玩笑,我確實是這樣做的。

我想我可以花一個下午來研究它,然後在吃晚飯的時候就可以完全掌握。畢竟,閱讀我自己的程式碼很容易,閱讀別人有什麼不同?

我們都知道接下來會發生什麼。可以這麼說,我當時的感受像一頭撞在了一堵文字牆上一樣。

[譯] 如何心平氣和地閱讀程式碼

我一次想學的東西太多了。許多初學者在第一次閱讀原始碼的時候也會犯同樣的錯誤。

心智模型是一點一點建立起來的,閱讀程式碼也應該如此。

不要去試圖以堅持努力來消化 1000 行程式碼,專注於一個主題。如果能夠細化到單個方法更好。

有一個細化的焦點能夠讓你分清什麼是相關的,什麼是不相關的。沒有必要去理會那些不相關的東西。

然而,選擇一個特定的主題並不能解決你的所有問題。知道它在程式碼庫中的位置仍然是個難題。

這就是第二步的問題了。

2. 找到一個切入點

Image Source: [https://glenelmadventblog.files.wordpress.com/2012/12/loose-thread.jpg](https://glenelmadventblog.files.wordpress.com/2012/12/loose-thread.jpg)

現在你有了一個想要學習的目標,接下來應該怎麼做?

幸運的是,程式語言附帶了檢查工具。

物件的類,類的祖先,堆疊跟蹤,還是某種方法的所有者,這是大多數語言都有的特性。無論你是想知道哪一個,一旦你開始分析程式碼庫,你會遇到一系列問題。

與其用文字來解釋這個概念,不如用程式碼展示來得更快。

開始分析

假設我想學習更多 ActiveRecord 的相關知識。然後我已經把重點縮小到了 belongs_to 方法上,現在我想了解它如何影響 ActiveRecord 模型。

ActiveRecord 是 Rails 的一部分,它是用 Ruby 構建的。Ruby 提供了大量開發工具。

我的第一種方法是使用除錯工具,比如用 pry gem 來剖析我的 ActiveRecord 模型。對於之前的假設,這就是我選擇除錯的模型的程式碼。

class Comment < ActiveRecord::Base
  belongs_to :creator, foreign_key: 'user_id', class_name: 'User'
  belongs_to :post
  binding.pry
  validates :body, presence: true
end
複製程式碼

注意 binding.pry 語句。當 Rails 遇到這行程式碼時,pry 將會在執行中期暫停應用程式並開啟命令列提示符。

下面是我研究 belongs_to 關聯的時候在控制檯使用的示例交換。

  • 我的所有的輸入內容都是在 pry > 之後。

  • => 顯示控制檯的輸出。

pry> class = belongs_to(:post).class
=> ActiveRecord::Reflection::AssociationReflection

pry> class.ancestors
=> [ActiveRecord::Reflection::AssociationReflection,        
    ActiveRecord::Reflection::MacroReflection,
     ...omitted for brevity ]

pry> defined? belongs_to
=> "method"

pry> method(:belongs_to).owner
=> ActiveRecord::Associations::ClassMethods
複製程式碼

如果你不太能理解 Ruby,並且這個交換讓你感到困惑,可以看看我的提示。

  • belongs_to :post 執行時,它返回一個 AssociationReflection 類的例項。

  • MacroReflectionAssociationReflection 的父類。

  • belongs_to 是一個類方法,它是在 ActiveRecord::Associations 內部的 ClassMethods 模組上定義的。

現在我有了一些線索,但是我應該遵循哪一條呢?因為我對 belongs_to 方法本身更感興趣,而不是它的返回值,所以我決定去檢視 ClassMethods 模組。

3. 跟隨線索

[譯] 如何心平氣和地閱讀程式碼

現在你已經有了想要跟隨的目標,剩下的就是跟隨它,直到找到你的答案。這似乎是一個簡單的步驟,但這正是大多數初學者犯錯的地方。

其中一個原因是,倉庫是沒有目錄的。我們任由維護人員以可讀的方式組織他們的檔案。

對於有很多維護者的大型專案,這通常不是問題。

但對於一個小專案,你可能會發現自己要費力地逐個處理檔案,逐個破譯名稱變數,然後就會多次遇到“這是從哪裡來的”的情況。

GitHub 搜尋

有一個工具可以幫助我們更容易完成這個任務,就是 GitHub 搜尋(我們假設你正在閱讀的專案是在 Github 上的)。Github 搜尋非常方便,因為他能夠顯示所有匹配搜尋查詢的檔案。它還能顯示符合查詢的內容在檔案中的位置。

[譯] 如何心平氣和地閱讀程式碼

為了得到最好的結果,你需要讓你的搜尋儘可能具體。這需要你對你想找的內容有一個概念。盲目的搜尋 Github 是沒有用的。

回到步驟 2 中的示例,我試圖在 ActiveRecord::Associations 中找到 ClassMethods 模組。用外行人的話來說,我正在尋找位於 ActiveRecord 模組內部的模組 Associations 中的 ClassMethods 模組。此外,我也在尋找 belongs_to 方法。


這是我的搜尋查詢。

[譯] 如何心平氣和地閱讀程式碼

結果準確地顯示了我正在尋找的東西。

[譯] 如何心平氣和地閱讀程式碼

belongs_to method inside of ClassMethods

可能需要更多研究


Github 搜尋將會顯著的縮小你的搜尋範圍。因此,你可以更容易的找到一個深入程式碼庫的切入點。

不幸的是,找到類或者方法不一定能給出問題的答案。你可能發現你從一個模組跳到另一個模組,直到你瞭解全域性。

在我的例子中,belongs_to 類把我導向了 BelongsTo 中的 build 方法。這讓我找到了 Association 的父類。

build method in BelongsTo class

build method in Association class

最後,我發現 belongs_to 讓 Rails 向我的模型新增了幾個例項方法,包括 getter 和 setter。它使用一種叫做超程式設計的高階程式設計技術來實現這一點。

Rails 還建立了一個 Reflection 類例項用於儲存 association 中的資訊。

來自 Rails API 文件:

Reflection 啟用了檢查 ActiveRecord 類和物件的關係和聚合的功能。例如,這種功能可以在 form builder 中使用,該 builder 接受一個 Active Record 物件然後根據其型別為所有屬性建立輸入欄位,並顯示它與其他物件的關聯。

挺簡潔的。

總結

雖然我不能保證解析別人的程式碼會很有意思,但這是值得的。它會給你的技術棧新增一項關鍵的技能,讓你更加自由。你將不會再依賴於完整的文件和示例,雖然文件很棒,但它並不是萬能的。正如 Jeff Atwood 說的:

你可能可以找到最好的,最權威和最新的文件,但是無論文件說什麼,原始碼才是最真實的。

所以快去練習這項技能吧!

我相信你現在肯定有一些你一直都想了解的東西。不要糾結於程式碼庫的大小。開啟你最喜歡的框架的倉庫然後開始學習。如果你按照我在文章中的步驟來,你很快就能成為一名原始碼專家。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章