也談如何閱讀程式原始碼

發表於2015-04-23

這周完成了一個意料之外的工作,我把python的wtfroms, voluptuous,logging三個包的程式碼讀了,還讀得挺high的。
之前我一直覺得讀原始碼是件痛苦的事情,不過不知怎麼的不怕了,還挺享受的。所以我總結了一下讀程式碼的心得,分享一下。

閱讀程式碼有兩點最重要:

1. 理解。閱讀程式最重要的是理解程式,包括幾個方面:1)理解每行程式碼做了什麼,2)理解作者設計的意圖,3)考慮作者都沒發現的問題。
2. 提出問題,解決問題。讀到沒有見過的庫函式,遇到沒有見過的語法,遇到沒有見過的技術,先不要著急google,
先考慮一下你遇到的是什麼問題,然後使用網路(google, stackoverflow)找答案,沒有徹底解決的疑惑要用筆記下來,不放過疑問。

我現在來示範一下。

從wtforms開始,程式碼在此https://github.com/wtforms/wtforms

第一個遇到的問題,也是核心問題:

Q: wtforms是幹什麼的?
A: 它是解決html表單驗證的工具。

(OK,可能你有更好的答案。不過在沒讀程式碼前,這可能是你能想到的最好的答案。當你對程式碼的理解加深了,你會有更好的答案的。)

我們來看一下程式碼的目錄。

docs,tests這些輔助都不是核心,不重要。gitignore檔案,travis配置檔案,python setuptools檔案都不重要,略過它們,找到重點,重點在wtforms資料夾。

進入這個目錄。

第二個問題是瞭解作者是如何分割各個模組的?

如何分割模組就是作者的想法了,要讀懂程式碼得了解他的想法。

如果一眼看不明白,可以找文件來讀。http://wtforms.readthedocs.org/en/latest/

讀完後就應該大致明白,wtforms分為幾個關鍵的物件

  • form: 負責對錶單建模
  • field: 負責建模每個表單的欄位
  • validator: 負責驗證每個欄位。
  • widget: 負責在html上渲染。

所以我們看到在這個目錄裡

  • form.py
  • validators.py
  • fields
  • widgets

是要讀的程式碼,其他可以先不看,因為相對來說不是核心。

我們從form.py開始 https://github.com/wtforms/wtforms/blob/1.0.4/wtforms/form.py

實事上即便是這檔案也不是要全部讀的。

首先看最上層的構築,這段程式碼裡面這些行是主結構:

這三行通過最後一行繫結到一起。

你看不懂第二?先猜一下FormMeta是繼承自type型別的,看不懂第三行?找到了關鍵字metaclass,直接google “python metaclass” 查一下網上的資料。弄明白python metaclass。

同一級別的還有一行:

但是,似乎和前面三者沒有關係,所以暫時忽略掉。

然後看下面一層的程式碼。你會發現有很多帶有兩個下劃線的函式,它們的函式體都很短,
google 一下知道這些函式是處理如何取和存物件的屬性的,而且沒有什麼複雜的操作,
我們現在的目的是搞明白form如何工作的,所以先忽略他們,到有需要的時候再看。
重要的是那些作者自己定義的函式。以及大塊的函式,比如初始化函式__init__

找到了重點程式碼段,讀就是了,理解每一行。

Q: 那麼那些不是很重要的程式碼該怎麼讀?
A: 等需要用到的時候去讀。閱讀程式碼並不能真正理解程式碼,在使用的時候你會發現更多的問題,
所以需要依靠除錯來理解程式碼。

幸好python是動態語言,而且有virtualenv,和DVCS,我只需要print語句就可以解決大多數的除錯問題。
為了搞明白wtforms是怎麼工作的,我邊寫程式碼,邊除錯了幾個小時。

總結一下如何讀程式碼:

實際上不難!

。。。。。。。還沒完。。。。。。

@Philip_Tzou 向我推薦了voluptuous這個庫 https://github.com/alecthomas/voluptuous

我吃驚得發現原來validator的實現可以用這樣完全不同的思考方式。

wtforms使用的建模方法是將一個html表單看做是form object,每一個input標籤是一個form field object,然後在每一個field object上進行驗證操作,最後可以通過widget渲染成html元素。

而voluptuous使用了另一種思路,它沒有對form建模,所以也沒有form object,它只有驗證器!你要做的是按照需要處理的物件來拼裝同樣模式的驗證器。

所以我後來考慮了這兩者思考方式的不同。

Q: wtform的作者為了解決什麼問題?voluptuous的作者又為了解決什麼問題?(記得我在示範開始的時候提的第一個問題了嗎?)
A: wtform的作者要解決如何驗證html form的問題,voluptuous的作者要解決的事如何驗證任意python物件。雖然兩個工具都能夠用來

解決表單驗證,但是前者更專注於網頁的POST請求,所以程式要處理html頁面渲染的問題,這算是相對重量級的應用場合。

另外作者考慮到要和ORM層的對接,甚至有了一個populate_obj這個函式。

而voluptuous的作者單純對python object的驗證可以用在輕量級的場合,比如ajax引數驗證的情況。

相關文章