- 浏览: 4821278 次
- 性别:
- 来自: 上海
博客专栏
-
robbin谈管理
浏览量:137051
文章分类
最新评论
-
xly1981:
领导者是团队的灵魂。深入一线的过程,包括代码review,能帮 ...
robbin谈管理:改造团队的经验(2) -
jiehuangwei:
像这种总结比较性的ppt文档可以多发啊
Web并发模型粗浅探讨 -
linux1308:
看完学习到了很多东西,感谢推荐!
推荐一篇很好的RoR部署方案性能评测 -
zweite:
直接对搜索的结果进行缓存是不是会更快一点呢
漫谈应用缓存的命中率问题 -
kaogua:
现在已经是ruby2.0了, 不知道这个的效率是怎么样的, 是 ...
Ruby作为服务器端应用已经成熟了
在参与这个讨论的过程中,产生了一个新的话题,很想和大家探讨一下:
http://www.iteye.com/topic/33890
这是一个存在于大家心里常识了。我承认我自己在潜意识里面也觉得静态强类型语言适合开发复杂,大型系统。而弱类型脚本语言不适合开发太复杂,太大型的项目。但是在参与这个讨论过程中,我突然开始置疑这个观点,事实究竟是不是这样的呢?
先定义一下标准:
强类型语言(静态类型语言)是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行。例如C/C++/Java/C#
弱类型语言(动态类型语言)是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
对于像Java来说,IDEA/Eclipse确实在代码感知能力上面已经非常强了,这无疑能够增加对大型系统复杂系统的掌控能力。但是除了Java拥有这么强的IDE武器之外,似乎其他语言从来没有这么强的IDE。C#的Visual Studio在GUI开发方面和Wizard方面很强,但是代码感知能力上和Eclipse差的不是一点半点。至于Visual C++根本就是一个编译器而已,羞于提及Visual这个字眼。更不要说那么多C/C++开发人员都是操起vi吭哧吭哧写了几十万行代码呢。特别是像Linux Kernel这种几百万行代码,也就是用vi写出来的阿,够复杂,够大型,够长生命周期的吧。
也就是说静态类型语言可以保障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语言。而显然静态类型语言基本都不满足这个要求。
那静态类型语言的优势究竟是什么呢?我认为就是执行效率非常高。所以但凡需要关注执行性能的地方就得用静态类型语言。其他方面似乎没有什么特别的优势。
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
如果x.zzz1()和y.zzz2()可能会抛出exception呢?
从我举的这个例子当中,logging这类的操作本身就应当是没有副作用的,所以也不会去调用那些会产生副作用的函数和方法。
退一步讲,如果这类应当没有副作用的操作里面干了有副作用的这些事情而且抛出异常,实际上,程序本身在之前就已经处于不正常状态了,让logging这类操作来捕获或反映这个状态,显然是不合适的。
当年C++死守企业应用领域的时候,也是对Java这么说的。
当年C++死守企业应用领域的时候,也是对Java这么说的。
我在slashdot上类似话题的讨论上曾经看到过有人抱怨动态语言,那个哥们是从事银行系统的,大概有10万行的python代码,最后因为细小隐错不断而觉得无法维护,貌似要转到java平台。(如果把slashdot上近两年来关于ruby和python的帖子和评论看一边,大概还能够找到这个跟贴)
从这哥们的描述来看,他的主要问题是没有单元测试或者单元测试没有达到语句覆盖或者更强的弱条件组合覆盖,从而导致某些非正常流程发生时,流经这些未被测试的语句导致语法错误而最终整个程序都挂掉.对于业务系统来说,这是非常严重的事情。就像我前面说的那样,我自己的程序就曾经不止一次死在logging语句上,因为最初我也不测试这类语句的可通过性。
至于单元测试有没有用,三五人的项目几千行的代码是看不出来的。其实,作坊式开发照样能够做出很多东西来,5年前国内的开发方式基本上是没有单元测试的,照样也能玩得转。
但是,就我自己的体验而言,虽然我并不遵循TDD,但单元测试是足够详尽的,而这个测试网给我的置信度(尤其是在修改代码和较大规模重构时)是之前不可想象的。我估计上千行的程序,就能够在渐增式的单元测试中尝到好处。
不过,这是个哲学问题。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
如果x.zzz1()和y.zzz2()可能会抛出exception呢?
exception specification 可以是类型的一部分的。
其实静态类型语言,除了性能方面的考量之外,最大的优势就是可以提供静态类型安全,编译器可以检查你的每一个函数调用是不是书写了正确的名字,是不是提供了正确类型的参数。这样一个系统,配合自定义类型的功能,可以让很多错误(比许多人想象的要多)在编译时就能被发现和定位。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
如果x.zzz1()和y.zzz2()可能会抛出exception呢?
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。
问题是Unit Test干什么去了?不要告诉我,你敢写Unit Test覆盖不到的代码!
hehe. 单元测试和单元测试还不一样。
以前写的一段文字:
http://www.iteye.com/post/133586
简单的说,如果采用动态语言,单元测试上的工作量要比静态语言的多很多。
最简单的情况,比如:
这一句。在静态语言中,基本上通过了编译就没事了.如果一定要做测试,那是得了测试强迫症了,就好像对getter/setter也测试一边一样。
而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。而且,对于动态语言,getter/setter的调用方,其语句也是需要被测试到的。
其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。
问题是Unit Test干什么去了?不要告诉我,你敢写Unit Test覆盖不到的代码!
然而Ruby这样的语言,虽然看上去更加符合“描述问题即解决问题”,但是对于同一段逻辑,同样可以满足要求,写法上却差别很大。我曾经见过用1行写出来的解决数读算法的Ruby解法,谁能看懂?
对这一点我也有类似的看法,有人曾经用例子试图说明ruby在写代码时如何短小,经常写在一行,其实逻辑单元都一样多,反而降低了可读性。看上去并不诱人。
其实一两行代码演示不能说明什么问题。不妨试着分别用两种语言去做同一件稍微有点复杂度的事情。
静态类型的优势,就在于有编译期类型检查这个步骤。
静态类型,迫使程序员采用强契约。模块实现者和模块调用者都要遵守一个带有强参数类型的强契约。
如果类型是必须声明的,可读性倒是有一点优势,因为一眼可以看到这个变量的类型。
不过有些静态语言采用type inference,不需要声明。和动态类型语言一样,使用富有含义的名字,表示变量的意义。
如果不在乎编译期类型检查这个功能,就没有优势。如果在乎这个功能,就有优势。
正如,如果一个程序员不在乎减少代码量这个优势,那么Ruby就没有什么优势。
其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。
比如动态类型
这个写法和静态类型的
后者验证的不仅仅是调用方传入的参数类型如何,而且也验证了针对这个类型的传入参数a这个函数能够干些什么。在某种意义上说,这也是一个解耦合的做法。调用方只需要确保参数类型正确,方法执行方确保自身内部的执行序列在语法上必然可以执行。调用方只需要根据a函数的较为概略的文档知道要传入一个什么类型,会有什么结果发生就可以了,是相对黑盒的。
而对前者而言,a的这个文档不仅仅要说明干什么事情,而且要说明怎么干的(即对传入参数干了些什么事情),如果传入的arg不支持被这么干,就不能把它传进去。这个说明是相对白盒的。这里其实有个很有意思的问题,既然我对传入参数有要求,为什么不把它显式固定下来。
另一方面,在实际的处理过程中,如果采用了更多的测试,是可以排除动态类型调用中由于参数误传入而导致的错误的。但是,有一点不可否认,这个错误会在被调用方抛出,针对被调用方是框架或库的情况,有时候会出现烦人的情况,不利于准确定位。
应该说强类型/弱类型和动态类型/静态类型还是有一些微妙的区别的。几年前我也犯过与robbin一样的直觉错误.
静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求.
动态类型语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
强类型语言是一旦变量的类型被确定,就不能转化的语言。实际上所谓的貌似转化,都是通过中间变量来达到,原本的变量的类型肯定是没有变化的。
弱类型语言则反之,一个变量的类型是由其应用上下文确定的。比如语言直接支持字符串和整数可以直接用 + 号搞定。当然,在支持运算符重载的强类型语言中也能通过外部实现的方式在形式上做到这一点,不过这个是完全不一样的内涵
通常的说,java/python都算是强类型的,而VB/Perl/C都是弱类型的.
不过相比于动态/静态语言的分类,强类型/弱类型更多的是一个相对的概念。
http://www.iteye.com/topic/33890
引用
是像Java或者C#这样强类型的准静态语言在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中也有着非常强的优势
这是一个存在于大家心里常识了。我承认我自己在潜意识里面也觉得静态强类型语言适合开发复杂,大型系统。而弱类型脚本语言不适合开发太复杂,太大型的项目。但是在参与这个讨论过程中,我突然开始置疑这个观点,事实究竟是不是这样的呢?
先定义一下标准:
强类型语言(静态类型语言)是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行。例如C/C++/Java/C#
弱类型语言(动态类型语言)是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
引用
观点一:静态类型语言因为类型强制声明,所以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语言。而显然静态类型语言基本都不满足这个要求。
那静态类型语言的优势究竟是什么呢?我认为就是执行效率非常高。所以但凡需要关注执行性能的地方就得用静态类型语言。其他方面似乎没有什么特别的优势。
评论
25 楼
charon
2006-11-14
cookoo 写道
charon 写道
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) .....
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
如果x.zzz1()和y.zzz2()可能会抛出exception呢?
从我举的这个例子当中,logging这类的操作本身就应当是没有副作用的,所以也不会去调用那些会产生副作用的函数和方法。
退一步讲,如果这类应当没有副作用的操作里面干了有副作用的这些事情而且抛出异常,实际上,程序本身在之前就已经处于不正常状态了,让logging这类操作来捕获或反映这个状态,显然是不合适的。
24 楼
floating
2006-11-14
robbin,你在开发JavaEey时有没有做一些严格的建模工作?比如现在重要的class是不是基本上在设计阶段都考虑到了?还是你认为用RoR就应该遵循RoR提倡的Agile方式进行开发?
23 楼
dongbin
2006-11-14
引用
大型角本?不好意思,这个不知道是什么样子的,unix与linux下成堆成堆的角本都是perl写的,别的语言想抢这个市场也不容易
当年C++死守企业应用领域的时候,也是对Java这么说的。
22 楼
dongbin
2006-11-14
引用
大型角本?不好意思,这个不知道是什么样子的,unix与linux下成堆成堆的角本都是perl写的,别的语言想抢这个市场也不容易
当年C++死守企业应用领域的时候,也是对Java这么说的。
21 楼
fyol
2006-11-14
我认为分清应用类型是主要的。
传统win32下gui程序的开发,大型系统会用Delphi、VC、VB
但大型web应用肯定是php、java、asp
大型角本?不好意思,这个不知道是什么样子的,unix与linux下成堆成堆的角本都是perl写的,别的语言想抢这个市场也不容易
Ruby的兴起不是因为他是动态语言或什么东西,是因为java下面从structs到spring都没有降低框架的复杂性,所以rails这个框架插在哪儿都会开花
但时间会让java、c#、Python等来削除这些差距
因此:如果ror不能快速壮大,多半也会死在半路上,昙花一现
传统win32下gui程序的开发,大型系统会用Delphi、VC、VB
但大型web应用肯定是php、java、asp
大型角本?不好意思,这个不知道是什么样子的,unix与linux下成堆成堆的角本都是perl写的,别的语言想抢这个市场也不容易
Ruby的兴起不是因为他是动态语言或什么东西,是因为java下面从structs到spring都没有降低框架的复杂性,所以rails这个框架插在哪儿都会开花
但时间会让java、c#、Python等来削除这些差距
因此:如果ror不能快速壮大,多半也会死在半路上,昙花一现
20 楼
charon
2006-11-14
robbin 写道
to charon:
ruby on rails根本就没有getter/setter方法,你还有啥好测试的呢?
其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。
另外,缺少单元测试没有你说的那么恐怖。我们现在就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐怖。
ruby on rails根本就没有getter/setter方法,你还有啥好测试的呢?
其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。
另外,缺少单元测试没有你说的那么恐怖。我们现在就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐怖。
我在slashdot上类似话题的讨论上曾经看到过有人抱怨动态语言,那个哥们是从事银行系统的,大概有10万行的python代码,最后因为细小隐错不断而觉得无法维护,貌似要转到java平台。(如果把slashdot上近两年来关于ruby和python的帖子和评论看一边,大概还能够找到这个跟贴)
从这哥们的描述来看,他的主要问题是没有单元测试或者单元测试没有达到语句覆盖或者更强的弱条件组合覆盖,从而导致某些非正常流程发生时,流经这些未被测试的语句导致语法错误而最终整个程序都挂掉.对于业务系统来说,这是非常严重的事情。就像我前面说的那样,我自己的程序就曾经不止一次死在logging语句上,因为最初我也不测试这类语句的可通过性。
至于单元测试有没有用,三五人的项目几千行的代码是看不出来的。其实,作坊式开发照样能够做出很多东西来,5年前国内的开发方式基本上是没有单元测试的,照样也能玩得转。
但是,就我自己的体验而言,虽然我并不遵循TDD,但单元测试是足够详尽的,而这个测试网给我的置信度(尤其是在修改代码和较大规模重构时)是之前不可想象的。我估计上千行的程序,就能够在渐增式的单元测试中尝到好处。
不过,这是个哲学问题。
19 楼
Elminster
2006-11-14
cookoo 写道
charon 写道
dongbin 写道
引用
而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) .....
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
如果x.zzz1()和y.zzz2()可能会抛出exception呢?
exception specification 可以是类型的一部分的。
其实静态类型语言,除了性能方面的考量之外,最大的优势就是可以提供静态类型安全,编译器可以检查你的每一个函数调用是不是书写了正确的名字,是不是提供了正确类型的参数。这样一个系统,配合自定义类型的功能,可以让很多错误(比许多人想象的要多)在编译时就能被发现和定位。
18 楼
cookoo
2006-11-14
charon 写道
dongbin 写道
引用
而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) .....
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
如果x.zzz1()和y.zzz2()可能会抛出exception呢?
17 楼
whisper
2006-11-13
动不动态倒是无所谓
技术选择往往决定于成本
技术选择往往决定于成本
16 楼
bigpanda
2006-11-13
原来那个讨论的帖子我也仔细读了,也参与讨论了,觉得原作者的很多观点都似是而非。基本上是用过去的眼光来看问题。
现在的主流商业系统是由C++, java, C#这些主流语言写的,那是有历史多年形成的原因,技术本身这些语言和Smalltalk,ruby有什么优势? 用Smalltalk,ruby实现DSL容易多了。有下列原因造成了java, C#这些主流语言的成功:
1. 这些语言容易学,它们缺少高级的语言构造而使语义简单多了,不信去翻翻operation semantics和denotation semantics的书去,用operation semantics去分析这些语言不难,用denotation semantics去分析functional language就难多了。软件行业总的来讲还是缺人的,一大堆菜鸟在这个行当里当Coder,需求又这么大,找十个菜鸟用java上百上千行敲出来,比找个高手10行搞定还是容易的。
2. 高级语言需要高级的编译器,需要更快的计算机。比如说常规的递归,每次呼叫要生成新的Stack Frame,比iteration要慢,更耗费资源,后来出了个tail recursion, compiler/interpreter自己就可以解决这个问题了。写个factorial(x), return x==0?1:x*factorial(x-1); 一行搞定,底下让compiler自己生成goto去,比写iteration省事吧。用高级语言写,性能就会损失,我开始学C的时候那时还讲究怎么在关键地方用汇编提高效率,后来学C++还有人讨论C++的vtable太耗内存,java刚出来时的性能讨论,我就不用说了。现在随着编译器的进步,计算机速度的提高,在商业系统里都不是问题了。要用发展的眼光看问题,而不要用过去的眼光看问题。
说什么复杂的业务逻辑,商业系统技术上复杂个屁,再复杂能复杂过NP Complete?世界上有两种问题,一种是数学上有解的,一种是数学上暂时无解的,数学上暂时无解的就别干了。
商业系统的复杂在于组织上交流的困难,一个大公司,内部有个人能把商业流程搞得一清二楚就不错了,这个人还能把过程给软件人员讲清楚那简直是可遇不可求的事。这样用ruby反而有优势了,可以快速开发,促进交流,开发出个模型出来给商务人员看看,用用,自然交流起来就容易多了。
现在一个开发人员的开发效率比以前高多了,主要原因是因为开发语言和编译器的进步,这个趋势,只会继续下去,不要抱着过去的教条不放,java也是在不断改进的,加了reflection, 加了assert,加了泛型,下个版本,也要加脚本支持了。
未来是创造出来的,Hibernate打垮了CMP,Spring打垮了EJB,软件业的无穷魅力就在于有台计算机,别的都掌握在自己手里,现在动态语言的短处,慢慢都可以克服。
学习用新的思维去解决问题吧。
现在的主流商业系统是由C++, java, C#这些主流语言写的,那是有历史多年形成的原因,技术本身这些语言和Smalltalk,ruby有什么优势? 用Smalltalk,ruby实现DSL容易多了。有下列原因造成了java, C#这些主流语言的成功:
1. 这些语言容易学,它们缺少高级的语言构造而使语义简单多了,不信去翻翻operation semantics和denotation semantics的书去,用operation semantics去分析这些语言不难,用denotation semantics去分析functional language就难多了。软件行业总的来讲还是缺人的,一大堆菜鸟在这个行当里当Coder,需求又这么大,找十个菜鸟用java上百上千行敲出来,比找个高手10行搞定还是容易的。
2. 高级语言需要高级的编译器,需要更快的计算机。比如说常规的递归,每次呼叫要生成新的Stack Frame,比iteration要慢,更耗费资源,后来出了个tail recursion, compiler/interpreter自己就可以解决这个问题了。写个factorial(x), return x==0?1:x*factorial(x-1); 一行搞定,底下让compiler自己生成goto去,比写iteration省事吧。用高级语言写,性能就会损失,我开始学C的时候那时还讲究怎么在关键地方用汇编提高效率,后来学C++还有人讨论C++的vtable太耗内存,java刚出来时的性能讨论,我就不用说了。现在随着编译器的进步,计算机速度的提高,在商业系统里都不是问题了。要用发展的眼光看问题,而不要用过去的眼光看问题。
说什么复杂的业务逻辑,商业系统技术上复杂个屁,再复杂能复杂过NP Complete?世界上有两种问题,一种是数学上有解的,一种是数学上暂时无解的,数学上暂时无解的就别干了。
商业系统的复杂在于组织上交流的困难,一个大公司,内部有个人能把商业流程搞得一清二楚就不错了,这个人还能把过程给软件人员讲清楚那简直是可遇不可求的事。这样用ruby反而有优势了,可以快速开发,促进交流,开发出个模型出来给商务人员看看,用用,自然交流起来就容易多了。
现在一个开发人员的开发效率比以前高多了,主要原因是因为开发语言和编译器的进步,这个趋势,只会继续下去,不要抱着过去的教条不放,java也是在不断改进的,加了reflection, 加了assert,加了泛型,下个版本,也要加脚本支持了。
未来是创造出来的,Hibernate打垮了CMP,Spring打垮了EJB,软件业的无穷魅力就在于有台计算机,别的都掌握在自己手里,现在动态语言的短处,慢慢都可以克服。
学习用新的思维去解决问题吧。
15 楼
robbin
2006-11-13
to charon:
ruby on rails根本就没有getter/setter方法,你还有啥好测试的呢?
其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。
另外,缺少单元测试没有你说的那么恐怖。我们现在就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐怖。
ruby on rails根本就没有getter/setter方法,你还有啥好测试的呢?
其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。
另外,缺少单元测试没有你说的那么恐怖。我们现在就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐怖。
14 楼
charon
2006-11-13
dongbin 写道
引用
而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。
我的那句话的正确解读应该是:
在静态语言中,某些分支并不需要单元测试
这类地方,只需要语法正确就可以确保没有问题
比如,对于类似前面的那个warning语句,如果是出现在如下场景:
if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) .....
简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。
就这个差别。
13 楼
dongbin
2006-11-13
引用
而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支?
12 楼
charon
2006-11-13
dongbin 写道
引用
其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。
问题是Unit Test干什么去了?不要告诉我,你敢写Unit Test覆盖不到的代码!
hehe. 单元测试和单元测试还不一样。
以前写的一段文字:
http://www.iteye.com/post/133586
简单的说,如果采用动态语言,单元测试上的工作量要比静态语言的多很多。
最简单的情况,比如:
logger.warning(....)
这一句。在静态语言中,基本上通过了编译就没事了.如果一定要做测试,那是得了测试强迫症了,就好像对getter/setter也测试一边一样。
而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。而且,对于动态语言,getter/setter的调用方,其语句也是需要被测试到的。
11 楼
dongbin
2006-11-13
引用
其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。
问题是Unit Test干什么去了?不要告诉我,你敢写Unit Test覆盖不到的代码!
10 楼
robbin
2006-11-13
Lucas Lee 写道
downpour 写道
然而Ruby这样的语言,虽然看上去更加符合“描述问题即解决问题”,但是对于同一段逻辑,同样可以满足要求,写法上却差别很大。我曾经见过用1行写出来的解决数读算法的Ruby解法,谁能看懂?
对这一点我也有类似的看法,有人曾经用例子试图说明ruby在写代码时如何短小,经常写在一行,其实逻辑单元都一样多,反而降低了可读性。看上去并不诱人。
其实一两行代码演示不能说明什么问题。不妨试着分别用两种语言去做同一件稍微有点复杂度的事情。
9 楼
charon
2006-11-13
buaawhl 写道
静态类型的优势,就在于有编译期类型检查这个步骤。
静态类型,迫使程序员采用强契约。模块实现者和模块调用者都要遵守一个带有强参数类型的强契约。
如果类型是必须声明的,可读性倒是有一点优势,因为一眼可以看到这个变量的类型。
不过有些静态语言采用type inference,不需要声明。和动态类型语言一样,使用富有含义的名字,表示变量的意义。
如果不在乎编译期类型检查这个功能,就没有优势。如果在乎这个功能,就有优势。
正如,如果一个程序员不在乎减少代码量这个优势,那么Ruby就没有什么优势。
其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。
比如动态类型
def a(arg1): .... arg1.xxx(yyy,zzz)
这个写法和静态类型的
void a(Circle arg): arg.xxx(yyy,zzz)
后者验证的不仅仅是调用方传入的参数类型如何,而且也验证了针对这个类型的传入参数a这个函数能够干些什么。在某种意义上说,这也是一个解耦合的做法。调用方只需要确保参数类型正确,方法执行方确保自身内部的执行序列在语法上必然可以执行。调用方只需要根据a函数的较为概略的文档知道要传入一个什么类型,会有什么结果发生就可以了,是相对黑盒的。
而对前者而言,a的这个文档不仅仅要说明干什么事情,而且要说明怎么干的(即对传入参数干了些什么事情),如果传入的arg不支持被这么干,就不能把它传进去。这个说明是相对白盒的。这里其实有个很有意思的问题,既然我对传入参数有要求,为什么不把它显式固定下来。
另一方面,在实际的处理过程中,如果采用了更多的测试,是可以排除动态类型调用中由于参数误传入而导致的错误的。但是,有一点不可否认,这个错误会在被调用方抛出,针对被调用方是框架或库的情况,有时候会出现烦人的情况,不利于准确定位。
8 楼
charon
2006-11-13
robbin 写道
先定义一下标准:
强类型语言(静态类型语言)是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行。例如C/C++/Java/C#
弱类型语言(动态类型语言)是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
强类型语言(静态类型语言)是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行。例如C/C++/Java/C#
弱类型语言(动态类型语言)是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
应该说强类型/弱类型和动态类型/静态类型还是有一些微妙的区别的。几年前我也犯过与robbin一样的直觉错误.
静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求.
动态类型语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
强类型语言是一旦变量的类型被确定,就不能转化的语言。实际上所谓的貌似转化,都是通过中间变量来达到,原本的变量的类型肯定是没有变化的。
弱类型语言则反之,一个变量的类型是由其应用上下文确定的。比如语言直接支持字符串和整数可以直接用 + 号搞定。当然,在支持运算符重载的强类型语言中也能通过外部实现的方式在形式上做到这一点,不过这个是完全不一样的内涵
通常的说,java/python都算是强类型的,而VB/Perl/C都是弱类型的.
不过相比于动态/静态语言的分类,强类型/弱类型更多的是一个相对的概念。
7 楼
buaawhl
2006-11-13
静态类型的运行效率不一定高。
haskell的运行效率就不高。
汇编语言也不需要声明什么类型。
C 语言的类型也不是很强。
(根据charon下面的指出。发现这个地方写的有些不对。把静态类型等同于强类型了。)
----------------------------------
静态类型的优势,就在于有编译期类型检查这个步骤。
静态类型,迫使程序员采用强契约。模块实现者和模块调用者都要遵守一个带有强参数类型的强契约。
如果类型是必须声明的,可读性倒是有一点优势,因为一眼可以看到这个变量的类型。
不过有些静态语言采用type inference,不需要声明。和动态类型语言一样,使用富有含义的名字,表示变量的意义。
如果不在乎编译期类型检查这个功能,就没有优势。如果在乎这个功能,就有优势。
正如,如果一个程序员不在乎减少代码量这个优势,那么Ruby就没有什么优势。
haskell的运行效率就不高。
汇编语言也不需要声明什么类型。
C 语言的类型也不是很强。
(根据charon下面的指出。发现这个地方写的有些不对。把静态类型等同于强类型了。)
----------------------------------
静态类型的优势,就在于有编译期类型检查这个步骤。
静态类型,迫使程序员采用强契约。模块实现者和模块调用者都要遵守一个带有强参数类型的强契约。
如果类型是必须声明的,可读性倒是有一点优势,因为一眼可以看到这个变量的类型。
不过有些静态语言采用type inference,不需要声明。和动态类型语言一样,使用富有含义的名字,表示变量的意义。
如果不在乎编译期类型检查这个功能,就没有优势。如果在乎这个功能,就有优势。
正如,如果一个程序员不在乎减少代码量这个优势,那么Ruby就没有什么优势。
6 楼
zbird
2006-11-13
我更经常见到的是Java程序员屁大点事写几百行,Ruby几行就搞定了。哪一个更好读?
---------------
我怀疑是程序员的问题。
和语言的关系不大。
---------------
我怀疑是程序员的问题。
和语言的关系不大。
发表评论
-
WebObjects的来龙去脉
2012-06-08 15:30 7612在知乎上回答的一个问题:http://www.zhihu.co ... -
缓存技术浅谈
2010-09-24 18:08 21807有我在两年前写的一个培训的ppt,是介绍缓存知识的。有兴趣的可 ... -
对领域模型实现的总结性观点
2008-11-30 15:16 19557陶文发起的对领域模型 ... -
发现JBoss Seam很棒呀!有用Seam做过项目的吗?
2008-07-06 20:56 30323上周去见了一个朋友Mark,他应邀在Red Hat的研讨会上面 ... -
Spring Application Platform - SpringSource的应用服务器发布
2008-05-05 17:04 68932008年的5.1劳动节,Spring ... -
Warp framework - 一个相当有前途的Java轻量级Web开发框架
2008-03-06 15:24 22564Warp framework 是最近刚刚 ... -
Google Android会成为手机领域的微软Windows吗?
2007-11-16 17:23 9644Google gPhone手机的传言已经沸沸扬扬好几个月了,然 ... -
Java已经过时了吗?
2007-07-02 15:43 59721在四年以前,当我开始 ... -
Java开源框架发展的遐想
2007-05-23 00:04 34811上周末在杭州网侠大会做演讲的时候,我说:Java开源框架的革命 ... -
漫谈应用缓存的命中率问题
2007-05-09 14:19 26461这篇文章源自于: http://www.iteye.com/ ... -
为什么ORM性能比iBATIS好?
2007-05-06 11:16 34523缓存是有很多层次的,有web server前端缓存,有动态页面 ... -
点评Grails vs RoR
2007-03-30 17:49 8285Grails的革新和RoR相比,非常不彻底,很多地方兼容Jav ... -
缓存简述
2007-03-30 09:55 12263缓存实现的层面有很多: 1、对象缓存 由ORM框架提供,透明 ... -
JRuby0.9.8,正式宣布支持ruby on rails
2007-03-07 10:35 15667http://jruby.codehaus.org/ 自从S ... -
domain model的延伸讨论
2007-03-03 01:17 40709domain model,又称为领域模型,是Java企业应用讨 ... -
可以开始用Struts2.0了
2007-02-27 14:56 56101http://struts.apache.org/ Apac ... -
Google Guice - 比Spring快100倍的IoC容器
2007-02-27 14:46 58237http://code.google.com/p/google ... -
Spring2.0和EJB3.0随谈
2007-02-08 14:26 18464Spring自从2003年发布以来 ... -
Java程序员的推荐阅读书籍
2007-02-07 20:12 101364《Java程序员的推荐阅读 ... -
应该如何正确使用Quartz
2006-12-27 11:40 34233对于Web容器来说,最忌讳应用程序私自启动线程,自行进行线程调 ...
相关推荐
- **C 和 C++**:尽管 C 和 C++ 被认为是静态类型语言,但在某些情况下它们表现出了弱类型行为。例如,可以直接将整型变量与字符变量相加,而无需显式类型转换。 - **Perl 和 PHP**:这两种语言都是典型的弱类型语言...
静态类型语言要求在编译时声明变量类型,这有助于防止运行时类型错误,提高代码的稳定性和性能。 3. **浏览器内的编译和执行**:在浏览器内完成编译和执行可以减少对服务器的依赖,提高用户体验,因为用户无需等待...
Ravi编程语言是一种基于Lua 5.3的衍生语言,其设计目的是在保留Lua的简洁性和易用性的同时,引入了有限的可选静态类型。这使得Ravi在某些方面比纯动态类型的Lua更适合大型项目或性能敏感的应用,因为静态类型可以...
在IT行业中,静态页面与动态页面是两种常见的网页类型。静态页面是由HTML、CSS和JavaScript等静态文件组成的,内容在服务器端创建后直接发送到客户端,而动态页面则是在用户请求时由服务器端的脚本(如PHP、ASP、JSP...
**什么是静态类型检查?** 静态类型检查是在程序执行前进行的一种分析,它通过检查源代码中的类型声明来发现潜在的类型错误。与动态类型检查(Python默认的类型检查方式)不同,动态类型检查是在运行时进行的,这...
cpp-Empirical是一种专门针对时间序列分析的语言,它在C++的基础上构建,提供了静态类型的DataFrame数据结构。这个框架的设计目标是为科学家、工程师和分析师提供一个高效且易于使用的工具,以便处理和理解时间相关...
Kotlin编程语言,作为近年来备受关注的开源静态类型编程语言,已经在软件开发领域崭露头角。它由著名软件公司JetBrains发起,并且得到了全球开发者社区的广泛支持和贡献。Kotlin的设计理念旨在提高开发效率,降低...
JetBrains Kotlin ,一种开源的静态类型编程语言,由 JetBrains 和开源贡献者支持和开发,支持多平台编程是 Kotlin 的主要优势之一。它减少了为不同平台编写和维护相同代码所花费的时间 ,同时保留了本机编程的灵活性...
- **静态类型**:作为一种静态类型语言,Kotlin在编译阶段就进行了严格的类型检查,这有助于早期发现错误并提高代码质量。 - **类型推断**:Kotlin能够根据上下文自动推断变量的类型,这减少了显式类型声明的需求...
这个主题通常涉及广泛,包括静态类型语言和动态类型语言的对比,编译型语言与解释型语言的区别,以及各自在性能、开发效率、可维护性等方面的表现。 描述中的“NULL”表明没有提供具体的描述,但我们可以从常见的...
Java平台的多语言混合编程是指在Java虚拟机(JVM)上运行多种语言,包括静态类型语言和动态类型语言、命令式语言和声明式语言等。这种混合编程方式可以充分发挥Java平台的优势,实现跨平台、跨语言的开发。 Java...
静态页面生成通常分为两种类型:预渲染(Prerendering)和按需生成(On-Demand Generation)。 1. 预渲染:在项目构建阶段,静态页面生成器会遍历所有路由,根据模板和数据生成对应的HTML文件。这些文件会被上传到...
在IT行业中,动态网站与静态网站是两种常见的网页类型。动态网站主要依赖服务器端脚本,如ASP(Active Server Pages),来实时生成内容并交互,而静态网站则是预先编译好的HTML页面,直接由浏览器解释执行。后台ASP...
Python的语法较为宽松,支持动态类型,而C++则采用了静态类型系统,要求开发者在编写代码时明确指定类型。 2. **应用领域**:Python因其简单易学和丰富的库支持,在数据科学、机器学习、Web开发等领域受到欢迎。而...
4. **静态类型检查**:与动态类型语言不同,静态类型检查是在程序运行前进行的。通过这种方式,可以在代码执行前发现类型错误,避免运行时出错。Python本身是动态类型的,但PEP 484引入了对静态类型的支持,使得...
静态类型语言(如C++、Java)在编译时就确定了变量的类型,这种强制性类型检查可以在早期发现错误,提高代码安全性,并为编译器优化提供信息。相反,动态类型语言(如Python、JavaScript)在运行时才确定变量类型,...
一、静态页面的优势 1. **快速加载**:静态页面的内容在用户请求时不需要通过服务器处理,直接由浏览器解析,这使得页面加载速度更快,对于旅行者来说,快速获取信息是非常关键的。 2. **低维护成本**:静态页面的...
4. 静态类型:Go 是静态类型的,这在编译时就能发现类型错误,提高了代码的可靠性。 5. 简洁明了:Go 语言的语法简洁,易于学习和使用,减少了理解成本。 然而,Go 语言也有其不足: 1. 生态系统不成熟:相比于 ...
在Java编程语言中,静态方法是一种特殊类型的方法,它与类相关联,而不是与类的实例相关联。静态方法在类加载时就会被加载到内存中,因此它们可以在没有创建对象的情况下被调用。静态方法的继承和重写是面向对象编程...
在IT行业中,静态页面是一种常见的网页设计类型,它主要用于创建简单、快速加载且内容不需频繁更新的网站。"图片展示静态模板"标题暗示我们这里关注的是一个专门用于展示图片的静态网页模板,这种模板通常包含精心...