动态类型

2005年3月14日

我一直不愿对编程语言中静态类型和动态类型之间的争论发表任何意见。这是一个容易引起情绪的话题,人们似乎更倾向于争论而不是倾听。但由于我被问过几次,我将分享我的个人经验。我并不是想说服任何人,但我希望有人能从中学到一些东西。

当我第一次意识到这种区别时,我很快就被静态类型的优势说服了。我早期的编程经验是在 Basic 和 Fortran IV 中,那里的类型是有限的。然后我转向了 Pascal,它很快成为我喜欢的编程语言。

当我开始接触面向对象编程时,我同时使用 C++ 和 Smalltalk。有一段时间,我认为 Smalltalk 的动态类型是一个缺点,为了这个平台的出色生产力,这是一个可以接受的小代价。

当我参与一些中等规模的 Smalltalk 项目时,我开始真正质疑这一点。静态类型的普遍论点是,它可以捕获那些难以找到的错误。但我发现,在存在 自测试代码 的情况下,大多数静态类型会发现的错误,测试也能同样容易地发现。由于测试发现的错误远远超过类型错误,无论是在静态还是动态类型语言中,你都需要测试,所以拥有静态类型并没有给你带来多少好处。

看到其他人也经历了这种发现过程,真是很有趣。罗伯特·马丁和布鲁斯·埃克尔都从 C++ 转向 Python,发现了同样的情况。

然而,捕获错误并不是静态类型的唯一好处,而是一些我最近发现更明显的好处。

有一天,我发现自己试图理解一些写得很好的 Ruby 代码。我发现参数缺乏类型信息让生活变得很困难,我一直在对自己说“我到底得到了什么?”我在 Smalltalk 中并没有发现这个问题,原因有两个:出色的环境使启动调试器并查看你拥有什么变得很容易,其次,常见的约定是根据类型命名参数。(这是有道理的,因为 Smalltalk 具有关键字参数而不是位置参数,所以关键字解释了参数所扮演的角色。)

静态类型有用的另一个领域是,它允许编程环境提供更多帮助。这里的启示(就像很多事情一样)是 IntelliJ。有了像这样的 IDE,我真的感觉类型系统在帮助我。即使是像自动完成这样简单的事情,也得到了静态类型的极大帮助,领先的 IDE 可以做到更多。

尽管如此,在像 Smalltalk 和 Ruby 这样的语言中编程仍然有一种特别令人满意的感觉,我认为这与动态类型有很大关系。在 Camp 4 Coffee 与布鲁斯·埃克尔聊天时,我们都同意,静态/动态类型争论中最令人沮丧的事情之一是,很难用语言描述在动态类型语言中工作的优势。不知何故,当你在这种环境中编程时,事情似乎流动得更好,即使我在 emacs 中使用 Ruby 而不是 IntelliJ。(当然,Smalltalk 既有语言,也有一个可爱的编程环境。)

我怀疑这部分原因是语言的简洁性,它允许在语言中进行 领域特定语言。使用 Java 和 C# 等语言时,我总是觉得需要跳过文本才能理解正在发生的事情。

无论原因是什么,这种更好的流动性都会带来更多编程乐趣,即使环境较差。这似乎并不重要,谁在乎程序员是否开心?但我确实在乎,因为我真的很享受编程。我喜欢快速完成事情,而不必在那些阻碍我的思考和运行代码的废话上浪费时间。对我来说,这就是 Smalltalk 和 Ruby 的乐趣所在,也是我在任何个人项目中都会选择它们的理由。而乐趣也有商业价值,毕竟,动力是程序员生产力的主要因素。