“JVM上的多语言编程”这种说法还挺新颖的。这种说法是为了描述那些以Java代码为核心,但还用了一种或多种其他非Java JVM语言的项目。多语言编程通常是一种关注点分离的形式。如图7-3所示,非Java技术的作用可以分为三个层次。这张图有时被称为多语言编程金字塔,这要归功于Ola Bini。
金字塔中有三个明确的层次:特定领域层、动态层和稳定层。
图7-3 多语言编程金字塔
多语言编程的秘密
多语言编程之所以有意义,是因为不同的代码片段有不同的生存期。银行里的风险引擎可能会持续运行五年以上;而网站上的JSP页面可能只有几个月;最短命的启动代码可能只“活”几天。代码“活”得时间越长,越靠近金字塔的底部。
它代表了不同侧重点的相互折中,比如底部更关注性能和全面测试,而顶部侧重的是灵活性和快速部署能力。
表7-1给出了这三个层次的更多细节。
表7-1 三层多语言编程金字塔
这些层次中有特定的模式,静态类型语言更倾向于稳定层的任务。相反,能力不是那么强、通用性比较低的技术在金字塔的顶部更容易找到自己的位置。
金字塔中部给动态语言留出了很多位置。这也是最灵活的一层,大多数情况下在动态层内部或者在动态层和相邻层之间有重叠。
我们要对这张图继续深挖,看看Java语言为什么不是金字塔所有层次的最佳选择。接下来我们先来看看为什么要考虑非Java语言,然后给出一些选择非Java语言的重要标准。
7.3.1 为什么要用非Java语言
Java作为一种通用、静态类型的编译型语言有很多优势。这些品质使它成为实现稳定层功能的绝佳选择。但同样的特性放到金字塔上层就会变成负担。比如说:
- 重新编译太费工了;
- 静态类型不够灵活,重构起来时间可能会比较长;
- 部署的动静太大;
- Java的语法天然不适用于生产DSL。
Java项目重新编译的时长迅速攀升到了90秒到2分钟。这个长度足以严重打断开发人员的思路,并且对于只在生产环境中存活几个星期的代码来说,这种开发方式太糟糕了。
比较务实的办法是利用Java丰富的API和类库完成稳定层的繁重工作。
注意 如果你刚开始一个新项目,可能会发现其他稳定层语言(比如Scala)也具备非常重要的特性(比如卓越的并发支持)。然而在大多数情况下,不应该用其他种类的稳定语言重写正在使用的稳定层代码。
这时你可能会纳闷:“每一层都会面临什么样的编程挑战,我该选哪种语言?”一个优秀的Java开发人员知道,根本没有所谓的银弹,但当我们面对选择时,的确有一定的评估标准。我们不可能在这里把每个可能的选项都讨论到,所以在剩下的章节中,我们会集中讨论三种大多数Java开发人员可能都会面临的选择。
7.3.2 崭露头角的语言新星
接下来我们会挑三种,在我们看来可能最有生命力和影响力的语言。这些JVM语言(Groovy、Scala和Clojure)在多语言程序员心目中已经有了相当的分量。这三种语言为什么会得到大家的青睐?且听我们一一道来。
1. Groovy
Groovy语言是James Strachan在2003年发明的。它是动态的编译语言,语法跟Java很像,但更灵活。它被广泛用做脚本语言和快速原型语言,并且经常是开发人员或团队首选的非Java语言调研对象。你可以把Groovy看做是动态层的语言,它以擅长构建DSL著称。第8章主要介绍Groovy。
2. Scala
Scala是一门面向对象的语言,但也支持函数式编程。它的起源可以追溯到2003年,当时Martin Odersky正在用Java做一个与泛型相关的项目,结果却催生了Scala。它和Java一样,是静态类型的编译语言,但和Java不同,它做了大量的类型推断工作。也就是说它经常给人以动态语言的感觉。
Scala从Java中借鉴了很多东西,并且它的设计“修正”了Java中几个长期以来困扰开发人员的问题。Scala可以做稳定层语言,并且有些开发人员认为它可能会取代Java成为“JVM上的下一个大语言”。第9章介绍Scala。
3. Clojure
Clojure是由Rich Hickey设计的,属于Lisp家族的语言。它从Lisp中继承了很多语法特性(包括大量的括号1)。就像大多数Lisp语言一样,它是动态类型的函数式语言。它是编译型语言,但通常以源码形态发布(稍后解释)。Clojure还向它的Lisp核心中添加了相当可观的新特性(特别是在并发方面)。
1 Lisp的表达式是一个原子(atom)或表(list):原子(atom)又包含符号(symbol)与数值(number);表是由零个或多个表达式组成的序列,表达式之间用空格分隔,放入一对括号中。此处的括号应该是指内置的表达式。——译者注
Lisp通常被当做专家语言。Clojure在某种程度上来说要比其他Lisp语言容易掌握,然而这并不会影响其强大的力量(也非常适合测试驱动的开发风格)。但它可能还是徘徊在主流之外,只是狂热的爱好者手中的秘密武器,抑或遇到适合它的特殊工作才发光(比如有些金融应用程序发现它的功能组合非常有吸引力)。
Clojure通常被认为是动态层的语言,但由于它的并发支持以及其他一些特性,也能胜任很多稳定层语言的工作。第10章会重点介绍Clojure。
现在我们已经把可选择的一部分语言罗列出来了,接下来该讨论一下决定你做出选择的那些因素了。