动态语言与静态语言的区别

2,992 阅读11分钟
原文链接: www.cnblogs.com

一 、静态语言的优势到底在哪?

来自robbin 摘自 www.javaeye.com/article/339…

引用 是像Java或者C#这样强类型的准静态语言在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中也有着非常强的优势

 

这是一个存在于大家心里常识了。我承认我自己在潜意识里面也觉得静态强类型语言适合开发复杂,大型系统。而弱类型脚本语言不适合开发太复杂,太大型的项目。但是在参与这个讨论过程中,我突然开始置疑这个观点,事实究竟是不是这样的呢?

先定义一下标准:

静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求. 
动态类型语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。 
强类型语言是一旦变量的类型被确定,就不能转化的语言。实际上所谓的貌似转化,都是通过中间变量来达到,原本的变量的类型肯定是没有变化的。 
弱类型语言则反之,一个变量的类型是由其应用上下文确定的。比如语言直接支持字符串和整数可以直接用 + 号搞定。当然,在支持运算符重载的强类型语言中也能通过外部实现的方式在形式上做到这一点,不过这个是完全不一样的内涵 
通常的说,java/python都算是强类型的,而VB/Perl/C都是弱类型的. 

引用 观点一:静态类型语言因为类型强制声明,所以IDE可以做到很好的代码感知能力,因为有IDE的撑腰,所以开发大型系统,复杂系统比较有保障。

 

对于像Java来说,IDEA/Eclipse确实在代码感知能力上面已经非常强了,这无疑能够增加对大型系统复杂系统的掌控能力。但是除了Java拥有这么强的IDE武器之外,似乎其他语言从来没有这么强的IDE。C#的Visual Studio在GUI开发方面和Wizard方面很强,但是代码感知能力上和Eclipse差的不是一点半点。至于Visual C++根本就是一个编译器而已,羞于提及Visual这个字眼。更不要说那么多C/C++开发人员都是操起vi吭哧吭哧写了几十万行代码呢。特别是像Linux Kernel这种几百万行代码,也就是用vi写出来的阿,够复杂,够大型,够长生命周期的吧。

 

引用 观点二:静态语言相对比较封闭的特点,使得第三方开发包对代码的侵害性可以降到很低。动态语言在这点上表现的就比较差,我想大家都有过从网上下载某个JS包,然后放到项目代码里发生冲突的经历

 

也就是说静态类型语言可以保障package的命名空间分割,从而避免命名冲突,代码的良好隔离性。但是这个观点也缺乏说服力。

静态类型语言中C,VB都缺乏良好的命名空间分割,容易产生冲突,但是并没有影响他们做出来的系统就不够大,不够复杂。

而Visual C++开发的DLL版本冲突也是臭名昭著的,似乎C++的命名空间没有给它带来很大的帮助。

而动态类型语言中Ruby/Python/Perl都有比较好的命名空间,特别是Python和Perl,例如CPAN上面的第三方库成吨成吨的,也从来没有听说什么冲突的问题。

诚然像PHP,JavaScript这样缺乏命名空间的动态语言很容易出现问题,但是这似乎是因为他们缺乏OO机制导致的,而不是因为他们动态类型导致的吧?

说到大型系统,复杂业务逻辑系统,Google公司很多东西都是用python开发的,这也证明了动态类型语言并非不能做大型的复杂的系统。其实我个人认为:

动态类型语言,特别是高级动态类型语言,反而能够让人们不需要分心去考虑程序编程问题,而集中精力思考业务逻辑实现,即思考过程即实现过程,用DSL描述问题的过程就是编程的过程,这方面像Unix Shell,ruby,SQL,甚至PHP都是相应领域当之无愧的DSL语言。而显然静态类型语言基本都不满足这个要求。

那静态类型语言的优势究竟是什么呢?我认为就是执行效率非常高。所以但凡需要关注执行性能的地方就得用静态类型语言。其他方面似乎没有什么特别的优势。

若干评论:

1。看看yahoo吧,它是用PHP写的。给你用JAVA也可能做不出来那样的性能。

2。我的一点感觉,动态语言足够灵活,因此虽然它能够让人更集中精力思考业务逻辑的实现,同时也向人工智能的方向走得更近一些,但因此它也更依赖于开发人员本身的技术功底,初学者、中级开发者,难以很好的利用它。 而静态类型语言,与我们计算机教学的基本科目(c/pascal/basic)延续性比较好,所以对于刚毕业的学生而言,更好接受和学习。因此我觉得还是学习/培训/开发成本占主要因素。一个不太恰当的例子:javascript的正则表达式,虽然功能强大,但并不易理解和学习。一般只能copy/paste来用。所以很多情况下,还是宁愿手写标准js来处理。

3。我感觉类似Java这样的强类型的准静态语言还有一个重要的特点。一旦程序员基本掌握了语法规则和书写规范,写出来的程序的可读性会强很多,因为它本身的限制更多。在一个大型系统中,Team成员之间互相可以知道对方在写什么是非常关键的,这也成为了交流的重要基础。

然而Ruby这样的语言,虽然看上去更加符合“描述问题即解决问题”,但是对于同一段逻辑,同样可以满足要求,写法上却差别很大。我曾经见过用1行写出来的解决数读算法的Ruby解法,谁能看懂?

4。我更经常见到的是Java程序员屁大点事写几百行,Ruby几行就搞定了

5。静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求. 
动态类型语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。 
强类型语言是一旦变量的类型被确定,就不能转化的语言。实际上所谓的貌似转化,都是通过中间变量来达到,原本的变量的类型肯定是没有变化的。 
弱类型语言则反之,一个变量的类型是由其应用上下文确定的。比如语言直接支持字符串和整数可以直接用 + 号搞定。当然,在支持运算符重载的强类型语言中也能通过外部实现的方式在形式上做到这一点,不过这个是完全不一样的内涵 
通常的说,java/python都算是强类型的,而VB/Perl/C都是弱类型的. 
不过相比于动态/静态语言的分类,强类型/弱类型更多的是一个相对的概念。

6。如果采用动态语言,单元测试上的工作量要比静态语言的多很多

robbin 回这一条。其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。

另外,缺少单元测试没有你说的那么恐怖。我们现在就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐怖。

7.商业系统的复杂在于组织上交流的困难,一个大公司,内部有个人能把商业流程搞得一清二楚就不错了,这个人还能把过程给软件人员讲清楚那简直是可遇不可求的事。这样用ruby反而有优势了,可以快速开发,促进交流,开发出个模型出来给商务人员看看,用用,自然交流起来就容易多了。

现在一个开发人员的开发效率比以前高多了,主要原因是因为开发语言和编译器的进步,这个趋势,只会继续下去,不要抱着过去的教条不放,java也是在不断改进的,加了reflection, 加了assert,加了泛型,下个版本,也要加脚本支持了。

8.其实静态类型语言,除了性能方面的考量之外,最大的优势就是可以提供静态类型安全,编译器可以检查你的每一个函数调用是不是书写了正确的名字,是不是提供了正确类型的参数。这样一个系统,配合自定义类型的功能,可以让很多错误(比许多人想象的要多)在编译时就能被发现和定位。

9.我在slashdot上类似话题的讨论上曾经看到过有人抱怨动态语言,那个哥们是从事银行系统的,大概有10万行的python代码,最后因为细小隐错不断而觉得无法维护,貌似要转到java平台。(如果把slashdot上近两年来关于ruby和python的帖子和评论看一边,大概还能够找到这个跟贴) 
从这哥们的描述来看,他的主要问题是没有单元测试或者单元测试没有达到语句覆盖或者更强的弱条件组合覆盖,从而导致某些非正常流程发生时,流经这些未被测试的语句导致语法错误而最终整个程序都挂掉.对于业务系统来说,这是非常严重的事情。就像我前面说的那样,我自己的程序就曾经不止一次死在logging语句上,因为最初我也不测试这类语句的可通过性。 
至于单元测试有没有用,三五人的项目几千行的代码是看不出来的。其实,作坊式开发照样能够做出很多东西来,5年前国内的开发方式基本上是没有单元测试的,照样也能玩得转。 
但是,就我自己的体验而言,虽然我并不遵循TDD,但单元测试是足够详尽的,而这个测试网给我的置信度(尤其是在修改代码和较大规模重构时)是之前不可想象的。我估计上千行的程序,就能够在渐增式的单元测试中尝到好处。 
10.编译器对程序员的帮助到底有多大,这个还是要应人而异的。编译器能查出来的很多都属于打字错误,拼写错误。对于robbin来说,即使没有编译器,检查这种错误也是小菜一碟。可是对于经验不是很丰富的程序员来说,情况恐怕就大大不同了。毕竟程序员经验方面差异的一个重要方面就是Debug能力和经验的差异。对高手来说仔细读上两遍程序就能发现的错误,对一些新手来说可能会花上一两小时,这种情况我在实际项目中碰到很多次了。