这周完成了一个意料之外的工作,我把python的wtfroms, voluptuous,logging三个包的代码读了,还读得挺high的。
之前我一直觉得读源代码是件痛苦的事情,不过不知怎么的不怕了,还挺享受的。所以我总结了一下读代码的心得,分享一下。
阅读代码有两点最重要:
1. 理解。阅读程序最重要的是理解程序,包括几个方面:1)理解每行代码做了什么,2)理解作者设计的意图,3)考虑作者都没发现的问题。
2. 提出问题,解决问题。读到没有见过的库函数,遇到没有见过的语法,遇到没有见过的技术,先不要着急google,
先考虑一下你遇到的是什么问题,然后使用网络(google, stackoverflow)找答案,没有彻底解决的疑惑要用笔记下来,不放过疑问。
我现在来示范一下。
从wtforms开始,代码在此https://github.com/wtforms/wtformshttps://github.com/wtforms/wtforms
第一个遇到的问题,也是核心问题:
Q: wtforms是干什么的?
A: 它是解决html表单验证的工具。
(OK,可能你有更好的答案。不过在没读代码前,这可能是你能想到的最好的答案。当你对代码的理解加深了,你会有更好的答案的。)
我们来看一下代码的目录。docs,tests这些辅助都不是核心,不重要。gitignore文件,travis配置文件,python setuptools文件都不重要,略过它们,找到重点,重点在wtforms文件夹。
进入这个目录。
第二个问题是了解作者是如何分割各个模块的?
如何分割模块就是作者的想法了,要读懂代码得了解他的想法。
如果一眼看不明白,可以找文档来读。http://wtforms.readthedocs.org/en/latest/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
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
https://github.com/alecthomas/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参数验证的情况。