這周完成了一個意料之外的工作,我把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引數驗證的情況。