Contents
类似Python这种动态语言的一个疑惑
ZoomQuiet 按: 这是一个经典的学院派开发者进入Pythonic 世界的硬科幻级疑问...
初问
Zhang Jiawei <[email protected]> 发件人当地时间 发送时间 11:33 (GMT+08:00)。发送地当前时间:上午9:56。 ✆ 回复 [email protected] 发送至 python-cn <[email protected]> 日期 2010年12月25日 上午11:33 主题 [CPyUG] 类似Python这种动态语言的一个疑惑
codebase 中 merge 了别人的代码以后。即便双方都没有改动同一个文件,也可能出现这种情况:
- A 只改动了 a.py 的一个方法的传参个数。
- B 改动了 b.py, 并且 b.py 中调用了 a.py 中的那个方法改动前的版本。
merge 了两个文件以后, 程序员基本都不会意识到现在出了问题。
原因有两个:
- python 程序员基本不用什么IDE, 如果使用 pydev 之类, 大致还能依靠 IDE 在merge 以后看到这个错。
- python 没有编译的概念,没有机会看到编译器对这个语法问题的报错。
好了,现在只有等上线以后,通过某个事件触发这个bug了。
请问各位是杂么防范这种问题的?
- unit test ?
强答
沈崴 <[email protected]> 日期 2010年12月28日 上午10:58 主题 [CPyUG] Re: 类似Python这种动态语言的一个疑惑
On 12月25日, 上午3时33分, Zhang Jiawei <[email protected]> wrote:
关于这个问题,
- 首先,我并不认为这是一个真正的 bug。真正的 bug 是改动了 b.py 中接口的逻辑和用途,但是接口名和参数个数并没有变化。这种在编译语言中完全正常的,恰恰才是真正最为危险的情况。
而在讨论中,大家都在想办法保证参数个数必须一致的问题,我这里随便举个例子:
adduser(username, passwod) adduser(name, gender)
作为同名接口,都具有两个参数,甚至都是字符串类型的,而且无论在编译还是运行期都不会报错。似乎符合 “没有出错”这个判断 bug 的标准,但是,这会产生极为严重的问题 —— 真正的逻辑错误。
所以我想说的是:
试图使用静态检查,和使用 IDE 进行参数约束的想法,才是真正危险的!
- 需要明白,报错和 core dump 并不是真正的 bug,也不是敌人。
要写出真正安全,减少 bug 的好程序,就要反过来做,不仅要允许参数不一致,而且还要尽量制造这种错误。
- 除了在 python 和编译语言中都有的 assert 方法,python 提供了更多可以避免这种情况发生的机制。比如显式参数名调用:
如果这样调用 adduser(name='tom', gender='male') 就会出错,这时调用者 可以立即明白,逻辑上有问题了。你的程序就真正减少了一个 bug。
- 关于 python 中这些安全机制,我在一些场合已经讲过很多,大家可以补充。
所以,结论完全相反,比起静态语言,像 python 这种动态语言更难产生 "bug"。
- 使用 IDE 对于避免 bug 有一定优势也有劣势。至少 python 不会比静态语言更危险。
> 1. python 程序员基本不用什么IDE, 如果使用 pydev 之类, 大致还能依靠 IDE 在merge 以后看到这个错。
- ~ 当然我无论写 python,c\c++ 还是 java 之类都不会用 IDE,其实在你公司之外
许多人都是这样的。
> 2. python 没有编译的概念,没有机会看到编译器对这个语法问题的报错。
- 关于编译的问题,这里先不谈 .pyc .pyo。其实每个 .py 文件都像一个 .so / .dll 文件。如果静态语言这么搞,上面提到的这种小问题一样多,之所以静态语言看似没有这种问题,很大原因是因为它这么搞太麻烦了。
当然很多人对把静态语言搞成一种动态语言的这件牛逼的事情乐此不疲。
- 静态语言的项目,除去真的全部都是静态链接起来,的这种情况。一样会遇到你提到的困扰。
所以,这本身就不是一个动态语言的问题。
> 好了,现在只有等上线以后,通过某个事件触发这个bug了。
我想说的是:
即便上线了,当有问题时不出错,才是真正可怕的事情。
上线的程序,都需要从静态语言崩溃和动态语言报错中恢复的机制,和错误报告机制。 当然,当程序上线时,traceback 总比 core dump 要可爱得多。 而且动态语言调试又要方便一些,用户很快可以得到更新补丁。
- 所以结论又是相反的,上线以后,动态语言情绪要稳定得多。
> 请问各位是杂么防范这种问题的? > > unit test ?
所以结论是,不仅不防范,而且还要尽量制造和纵容这种所谓的错误。
继续
On 12月28日, 上午4时59分, Wei guangjing <[email protected]> wrote:
> 在 2010年12月28日 上午10:58,沈崴 <[email protected]>写道: > > 而在讨论中,大家都在想办法保证参数个数必须一致的问题,我这里随便举个例子: > > adduser(username, passwod) > > adduser(name, gender) > > 作为同名接口,都具有两个参数,甚至都是字符串类型的,而且无论在编译还是运行期 > > 都不会报错。 > > 静态语言是不会有这个问题的,因为不可能定义2个同名并有同样参数个数的方法。
两个同名并有同样参数个数的方法
c++ 可以 python 不行。
~沈崴 <[email protected]>
我的意思是,B 在项目里负责共享库 libB.so (相对于 b.py),里面实现了
adduser(username, passwd)
明天 B 把 libB.so 中这个接口改成了
adduser(name, gender) 或者 adduser(name, gender, age)
的情况
矫枉过正
Zhang Jiawei <[email protected]> 发件人当地时间 发送时间 20:38 (GMT+08:00)。发送地当前时间:上午10:03。 ✆ 回复 [email protected] 发送至 [email protected] 日期 2010年12月28日 下午8:38 主题 Re: [CPyUG] Re: 类似Python这种动态语言的一个疑惑
如果得出这样的结论,我感觉有些矫枉过正了。
- 真的是个bug, 因为用户访问到这个语句行的时候,报错了。
- 我们不可能要求无论谁在写参数列表的时候都用map。
- 我的案例实际上用IDE或者其他的静态检查机制其实就可以解决问题,而且安全省力,没有附加步骤。
- 您说的参数语义的内涵发生变化而导致的问题其实开辟了第二个案例。其实静态语言里也存在,用 map也解决不了。因为大家merge代码的时候仍旧没有人意识到这里有问题,只有调用的时候才会发现问题。靠 unit test 应该能检查出来。如果unit test没报错,那么错的也是对的。
- IDE 或者 静态检查 的确检查不出您开辟的第二案例,但不等于 IDE 或者静态编译就是危险的,他们在自己力所能及的范围内检测出某些问题即可。比如我的案例。
- 我还是觉得不用把事情扯到静态语言的动态链接上,事情很简单,适用范围没有那么大,就说两个py之间 和 两个 .c 之间都有互相调用,如果 .c 是静态编译,通过编译器的报错会比执行到py才报错安全的多。即便是动态链接,楼上的朋友说了,参数个数的变化至少是可以通过编译发现的,因为.h 变了。您的第二案例,无论是动态语言还是静态语言都没办法不通过Unit Test解决。
- 我的案例同样是上线了,有问题不出错,和您的案例一样可怕。我和您的案例同样在静悄悄的等待出错的机会。
所以我想说的是:
- 试图使用IDE和静态检查机制解决所有问题是危险的,但是进行参数约束还是安全的,起码参数的个数首先没问题,然后再用Unit Test去保证参数语义的准确。
我的结论依旧,动态语言的出错几率会比静态语言大。靠 静态检查 + Unit Test 双保险解决问题。除此以外自己给自己制造问题太折腾。
另:c/python 好说,我想像不出 java 不用 IDE还能用什么写?
反馈
创建 by -- ZoomQuiet [2010-12-29 02:05:43]