(转)为Java说句公道话

原文链接:http://www.yinwang.org/blog-cn/2016/01/18/java/?from=timeline&isappinstalled=1

原文链接已失效,本文从博客园搬过来!

  文/王垠

  有些人问我,在现有的语言里面,有什么好的推荐?我说:“Java。” 他们很惊讶:“什么?Java!” 所以我现在来解释一下。

  Java 超越了所有咒骂它的“动态语言”

  也许是因为年轻人的逆反心理,人们都不把自己的入门语言当回事。很早的时候,计算机系的学生用 Scheme 或者 Pascal 入门,现在大部分学校用 Java。这也许就是为什么很多人恨 Java,瞧不起用 Java 的人。提到 Java,感觉就像是爷爷那辈人用的东西。他们说,Java 老气,庞大,复杂,臃肿。

  某些 Python 程序员,在论坛里跟初学者讲解 Python 有什么好,其中一个原因竟然是:“因为 Python 不是 Java!” 他们喜欢这样宣传:“看 Python 多简单清晰啊,都不需要写类型……” 对于 Java 的无缘无故的恨,盲目的否认,导致了他们看不到 Java 很重要的优点,以至于迷失自己的方向。虽然气势上占上风,然而其实 Python 作为一个编程语言,是完全无法和 Java 抗衡的。

  在性能上,Python 比 Java 慢几十倍。由于缺乏静态类型等重要设施,Python 代码有 bug 很不容易察觉,察觉了也不容易 debug,所以 Python 无法用于构造大规模的,复杂的系统。你也许发现某些 startup 公司的主要代码是 Python 写的,然而这些公司的软件,质量其实相当的低。在成熟的公司里,Python 最多只用来写工具性质的东西,或者小型的,不会影响系统可靠性的脚本。

  静态类型的缺乏,也导致了 Python 不可能有很好的 IDE 支持,你不能完全可靠地重构(refactor)Python 代码。PyCharm 对于早期的 Python 编程环境,是一个很大的改进,然而理论决定了,它不可能完全可靠地达到“变量换名”等基本的 refactor 操作。

  在设计上,Python,Ruby 比起 Java,其实复杂很多。缺少了很多重要的特性,有毛病的“强大特性”倒是多了一堆。由于盲目的推崇所谓“正宗的面向对象”方式,所谓“late-binding”,这些语言里面有太多可以“重载”语义的地方,不管什么都可以被重定义,这导致代码具有很大的不确定性和复杂性。Python 和 Ruby 代码很容易被滥用,不容易理解,容易写得很乱,容易出问题。

  很多 JavaScript 程序员也盲目地鄙视 Java,而其实 JavaScript 比 Python 和 Ruby 还要差。不但具有它们的所有缺点,而且缺乏很多必要的,方便的特性,比如基本的 class 定义都没有。JavaScript 的各种“WEB 框架”,层出不穷,似乎一直在推陈出新,而其实呢,全都是在黑暗里瞎蒙乱撞。JavaScript 的社区以幼稚著称。你经常发现一些非常基本的常识,被 JavaScript“专家”们当成了不起的发现似的,在大会上宣讲。我看不出来 JavaScript 社区开那些会议,到底有什么意义,仿佛只是为了拉关系找工作。

  Python 凑合可以用在不重要的地方,Ruby 是垃圾,JavaScript 是垃圾中的垃圾。原因很简单,因为 Ruby 和 JavaScript 的设计者,其实都只是民科。

  Java 的“继承人”没能超越它

  最近一段时间,很多人热衷于 Scala,Clojure,Go 等新兴的语言,他们以为这些是比 Java 更现代,更先进的语言,以为它们最终会取代 Java。然而这些狂热分子们逐渐发现,Scala,Clojure 和 Go 其实并没有解决它们声称能解决的问题,反而带来了它们自己的毛病。这些毛病很多是 Java 没有的。

  关于 Go,我已经评论过很多了,有兴趣的人可以看这里。总之,Go 是民科加自大狂的产物,这里我就不多说它了。

  我认识一些人,开头很推崇 Scala,仿佛什么救星似的。我建议他们别去折腾了,老老实实用 Java。没听我的,结果到后来,成天都在骂 Scala 的各种毛病。但是没办法啊,项目上了贼船,不得不继续用下去。我不喜欢进行人身攻击,然而我发现一个语言的好坏,往往取决于它的设计者的水平,人品,和动机。很多时候我看人的直觉是异常的准,以至于依据对语言设计者的第一印象,我就能预测到这个语言将来会怎么发展。在这里,我想谈一下对 Scala 和 Clojure 的设计者的看法。

  Scala 的设计者 Martin Odersky,虽然在程序语言领域有所建树,发表了不少看似高深的学术论文( 其实很多是扯淡的),然而他对于语言的“设计”,其实并不是特别在行。所以我很惊讶的发现,有些非常基本的东西,Scala 都会搞错。由于 Odersky 是大学教授,名声在外,很多人想找他拿个 PhD,所以东拉西扯的,喜欢往 Scala 里面加入一些不明不白,有潜在问题的“特性”,其目的就是发 paper,混毕业。这导致 Scala 过度繁复,加入的特性很多后来被证明没有多大用处,反而带来了问题。学生把代码实现加入到 Scala 的编译器,毕业就走人不管了,所以 Scala 编译器里,就留下一堆堆的历史遗留垃圾和 bug。

  再来说一下 Clojure。当 Clojure 最初“横空面世”的时候,有些人热血沸腾地向我推荐。于是我看了一下它的设计者 Rich Hickey 做的宣传讲座视频。当时我就对他一知半解拍胸脯的本事,印象非常的深刻。Rich Hickey 真的是半路出家,连个 CS 学位都没有。可他那种气势,仿佛其他的语言设计者什么都不懂,只有他看到了真理似的。不过也只有这样的人,才能创造出“宗教”吧?Clojure 大力宣传的“特性”(什么 lazy 啊,pure 啊,transactional memory 啊),都是从别的语言道听途说抄过来,却又没能深刻理解其精髓。有些“函数式语言”的特性,本来就是有问题的,却不问青红皂白,为了“主义正确”,抄过来。所以最后你发现这语言是挂着羊头卖狗肉,说得头头是道,用起来怎么就那么蹩脚。

  Clojure 的社区,一直忙着从 Scheme 和 Racket 的社区抄袭思想,却又想标榜是自己的发明。比如 Typed Clojure,就是原封不动抄袭 Typed Racket。有些一模一样的基本概念,在 Scheme 里面都几十年了,恁是要改个不一样的名字,免得你们发现那是 Scheme 先有的。甚至有人把 SICP,The Little Schemer 等名著里的代码,全都用 Clojure 改写一遍,结果完全失去了原作的简单性和精华性。最后你发现,Clojure 里面好的地方,全都是 Scheme 已经有的,Clojure 里面新的特性,几乎全都有问题。我参加过一些 Clojure 的 meetup,可是后来发现,里面竟是各种喊着大口号的初学者,各种趾高气昂的民科,愚昧之至。

  盲目推崇 Scala 和 Clojure 的人们,很多最后都发现,这些语言里面的“新特性”,几乎都有毛病。它们里面最重要最有用的特性,其实早就已经在 Java 里了。有些人跟我说:“你看,Java 做不了这件事情!” 后来经我分析,发现他们在潜意识里早已死板的认定,非得用某种最新最酷的语言特性,才能达到目的。Java 没有这些特性,他们就以为 Java 做不了,非得用另外的语言。其实,如果你换一个角度来看问题,不要钻牛角尖,专注于解决问题,而不是去追求最新最酷的“写法”,你就能用 Java 解决它,而且解决得干净利落。

  如果现在要做一个系统,真的宁可用 Java,也不要浪费时间去折腾什么 Scala 或者 Clojure。错误的人设计了错误的语言,拿出来浪费大家的时间。

  Java 没有特别讨厌的地方

  Java 也许缺少一些方便的特性,然而长久以来用 Java 进行教学,用 Java 工作,用 Java 开发 PySonar,RubySonar,Yin 语言,…… 我发现 Java 其实并不像很多人传说的那么可恶。我发现自己想要的 95% 以上的功能,在 Java 里面都能找到比较直接的用法。剩下的5%,用稍微笨一点的办法,一样可以解决问题。

  很多人讨厌 Java,其实是因为早期的 GoF Design Patterns,试图提出千篇一律的模板,给程序带来了不必要的复杂性。然而 Java 语言本身,其实跟 Design Patterns 并不是等价的。Java 的设计者跟 Design Pattern 的设计者,完全是不同的人。你完全可以使用 Java 写出非常简单的代码,而不使用 Design Patterns。

  Java 有优秀的 IDE 支持

  我平时都用 IntelliJ 来写 Java 代码。我发现 IntelliJ 里面,有一些非常好的设计思想。其中很多功能,其实超越了所有的文本编辑器(Emacs,VIM……)。IntelliJ 让 Java 如虎添翼,开发起来感觉是在飞一样。

  用 IntelliJ 的时候,你不需要为“给变量起名字”之类的事情焦虑。因为 IntelliJ 有非常强大而友好的 refactor 功能,你可以非常迅速的换掉变量的名字。所以在第一次创造变量的时候,你不需要花心思去起一个完美的名字。用一个还算凑合的名字,把代码很快写出来,实验成功。然后再返回去看代码,把名字换成一个更合适的就可以。

  IntelliJ 还可以进行非常迅速的结构变换,这让你就像艺术家在构造一个雕塑作品。最开头我可以大刀阔斧,把代码劈成大致的形状,然后再把它仔细推敲,揉捏成更好,更容易理解,更具魅力的形状。

  结论

  我实在不忍心看着有些人被 Scala 和 Clojure 忽悠。如果没有超级高的性能和资源需求(可能要用C这样的低级语言),目前我建议就老老实实用 Java 吧。虽然不如一些新的语言炫酷,然而实际的系统,还真没有什么是 Java 写不出来的。少数地方可能需要绕过一些限制,或者放宽一些要求,然而这样的情况不是很多。

  编程使用什么工具是重要的,然而工具终究不如自己的技术重要。很多人花了太多时间,折腾各种新的语言,希望它们会奇迹一般的改善代码质量,结果最后什么都没做出来。选择语言最重要的条件,应该是“够好用”就可以,因为项目的成功最终是靠人,而不是靠语言。