再谈静态语言对动态语言的优势

在以前的讨论中,robbin曾经发起过关于静态语言和动态语言优势比较的帖子:

http://www.iteye.com/topic/33971

关于静态语言和动态语言的定义请看上面的帖子。

我想谈一下自己的观点。

我个人觉得,静态语言相对于动态语言有如下几个优势:

1. 运行的性能优势
2. 代码的可读性
3. 代码质量的安全、可靠和可预测性

而这些优势决定了静态语言更适合用于开发大型系统。

先看第一点,运行性能。尽管现在许多动态语言可以使用类似JIT的技术来优化运行效率,但是由于其动态变化的能力(如动态增加方法、属性等)使得其性能的优化无法达到象Java这种动态优化的程度。而对于很多大型软件系统来说,性能无疑是非常重要的质量要素。

再看第二点,代码的可读性。这里的代码可读性并不是指代码量多少的问题,有的时候代码少并不一定好读,而代码多也不一定难度。举一个简单的例子,用Java定义一个类如下:
[code]public class People {
String name;
int age;
List addresses;

public String getName() {
return name;
}

......
}
[/code]

在其他类的方法中,可以使用该类:
[code]public void printPeople(People people) {
String name = people.getName();
......
}
[/code]

而在一些动态语言中,我们可以动态生成People类(譬如从数据库的元数据中,或者某些配置文件中),并且也可以使用如下:

[code]function void printPeople(people) {
String name = people.name;
......
}
[/code]

显然,动态语言使得我们可以不定义People,不过这时问题来了,我们除了从上面的方法参数名字上知道可能是一个People实例以外,很难获得更多的信息,并且,即时知道了这是一个People实例,我们也不知道这个类到底有什么属性可以访问,有什么方法可以调用,我们可能需要去查阅数据库的表定义,或者相关文档,但是直接从代码中我们无法知道这些信息。

对于大型系统来说,代码可读性的重要程度有时并不比文档和测试低,系统要能够很好的维护,就需要有较好的可读性。

第三点是代码质量的安全、可靠和可预测性。其实这一条是最重要的。代码的可靠和结果可预测对大型的软件系统来说至关重要。但是为什么说动态语言会在这方面存在问题呢?并且即使测试也无法解决呢?因为动态语言太灵活了,以至于你无法预测很多的行为。

我们还是以上面的printPeople函数作为例子,简单的一个people参数,我们来看看到底有多少情况是我们无法确定的:
1. people真的是People的实例吗?
2. People类真的是我们期望的People类吗?没有别的程序修改了它的属性定义或者方法的定义?如果有别的程序在运行时修改了这个类的定义怎么办?
3. 随着整个系统的发展,People类本身会发生怎样的变化,这个变化和printPeople这个函数相关吗?

显然这些不确定是我们无法用单元测试解决的,而集成测试我们通常只能遍历最常见的组合路径,所以测试无法有效的覆盖这些不确定性。

为什么会有这么多的无法确定的事情呢,因为动态语言缺乏强制的约定(或者协议),这种约定的缺乏形成了动态语言的动态特性。而在静态语言中,静态类型的约束的重要性不在于它在编译时的的类型检查,而在于它在使用者和定义者两者之间建立了一种约定,而这种约定保证了他们之间的行为的可预测性。

当然,对动态语言来说,这三个缺点并不是没有办法,有一些办法可以缓解这些问题,如果性能问题可以通过增加硬件的方法缓解,可读性问题可以通过注释和文档来缓解,而可靠和可预测性可以通过统一的约定以及组建一个开发风格一致的团队来缓解。

然而总体来言,这些缺陷制约了动态语言用于大型系统的可能,试想一个代码行数超过几十万行,生命周期为5-10年或者更长的软件系统,用动态语言来实现还是需要承担相当大的风险的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值