锁定老帖子 主题:静态类型语言的优势究竟是什么?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-11-13
Lucas Lee 写道 downpour 写道 然而Ruby这样的语言,虽然看上去更加符合“描述问题即解决问题”,但是对于同一段逻辑,同样可以满足要求,写法上却差别很大。我曾经见过用1行写出来的解决数读算法的Ruby解法,谁能看懂? 对这一点我也有类似的看法,有人曾经用例子试图说明ruby在写代码时如何短小,经常写在一行,其实逻辑单元都一样多,反而降低了可读性。看上去并不诱人。 其实一两行代码演示不能说明什么问题。不妨试着分别用两种语言去做同一件稍微有点复杂度的事情。 |
|
返回顶楼 | |
发表时间:2006-11-13
引用 其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。 问题是Unit Test干什么去了?不要告诉我,你敢写Unit Test覆盖不到的代码! |
|
返回顶楼 | |
发表时间:2006-11-13
dongbin 写道 引用 其实编译期类型检查可以做的比想象的要多。不仅仅是确定了类型,而且确定了这个类型上可以做的操作。 问题是Unit Test干什么去了?不要告诉我,你敢写Unit Test覆盖不到的代码! hehe. 单元测试和单元测试还不一样。 以前写的一段文字: http://www.iteye.com/post/133586 简单的说,如果采用动态语言,单元测试上的工作量要比静态语言的多很多。 最简单的情况,比如: logger.warning(....) 这一句。在静态语言中,基本上通过了编译就没事了.如果一定要做测试,那是得了测试强迫症了,就好像对getter/setter也测试一边一样。 而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。而且,对于动态语言,getter/setter的调用方,其语句也是需要被测试到的。 |
|
返回顶楼 | |
发表时间:2006-11-13
引用 而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。 静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支? |
|
返回顶楼 | |
发表时间:2006-11-13
dongbin 写道 引用 而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支? 显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。 我的那句话的正确解读应该是: 在静态语言中,某些分支并不需要单元测试 这类地方,只需要语法正确就可以确保没有问题 比如,对于类似前面的那个warning语句,如果是出现在如下场景: if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) ..... 简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。 就这个差别。 |
|
返回顶楼 | |
发表时间:2006-11-13
to charon:
ruby on rails根本就没有getter/setter方法,你还有啥好测试的呢? 其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。 另外,缺少单元测试没有你说的那么恐怖。我们现在就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐怖。 |
|
返回顶楼 | |
发表时间: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,软件业的无穷魅力就在于有台计算机,别的都掌握在自己手里,现在动态语言的短处,慢慢都可以克服。 学习用新的思维去解决问题吧。 |
|
返回顶楼 | |
发表时间:2006-11-13
动不动态倒是无所谓
技术选择往往决定于成本 |
|
返回顶楼 | |
发表时间:2006-11-14
charon 写道 dongbin 写道 引用 而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支? 显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。 我的那句话的正确解读应该是: 在静态语言中,某些分支并不需要单元测试 这类地方,只需要语法正确就可以确保没有问题 比如,对于类似前面的那个warning语句,如果是出现在如下场景: if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) ..... 简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。 就这个差别。 如果x.zzz1()和y.zzz2()可能会抛出exception呢? |
|
返回顶楼 | |
发表时间:2006-11-14
cookoo 写道 charon 写道 dongbin 写道 引用 而在动态语言中,不管这句话在哪个分支,都必须被测试到一边,否则,程序死在这种地方,真是会哭死。
静态语言的每一个分支就不需要单元测试了么?编译器检验每一个条件分支? 显然,你写的这句反问要表达的意思并不是我的原话的逆否命题。 我的那句话的正确解读应该是: 在静态语言中,某些分支并不需要单元测试 这类地方,只需要语法正确就可以确保没有问题 比如,对于类似前面的那个warning语句,如果是出现在如下场景: if( xxx > 0) logger.warning('...' + x.zzz1() + y.zzz2()) ..... 简单的说,在静态语言中,不论这句程序在哪里,我都不会去测试它。但在动态语言中,我必须保证有一个测试用例流过warning这个语句。 就这个差别。 如果x.zzz1()和y.zzz2()可能会抛出exception呢? exception specification 可以是类型的一部分的。 其实静态类型语言,除了性能方面的考量之外,最大的优势就是可以提供静态类型安全,编译器可以检查你的每一个函数调用是不是书写了正确的名字,是不是提供了正确类型的参数。这样一个系统,配合自定义类型的功能,可以让很多错误(比许多人想象的要多)在编译时就能被发现和定位。 |
|
返回顶楼 | |