InfoQ:
你们项目里面是不是大多数人都是Java程序员?他们学Scala容易么?
是啊,我们所有人都有很丰富的Java开发经验。最开始的四人小组学Scala学的很开心:经常是一个人发现了一个Scala的新特性,然后就激动不已,跟整个团队分享。那种冲动已经很久没有在用Java
的时候出现了。我们在共同学习,所以这个过程还不错。最开始的几周里,偶尔出现这种情况,我们打算用很体面的Scala的编程方式来实现一些功能,但就是搞不明白该怎么写。而且最关键的是,这儿要是用Java的话早就写完了,这就更让人泄气了。我们有几次受不了了,回家的时候说,“明天就换成Java
吧。”但每天早上都会迎来一个新的开始,我们继续往前走。
然后又有十个Java程序员来写Scala代码。每个人的学习方式和速度都不一样,这也司空见惯了。但他们都走过来了,到现在要是碰到非得写Java不可的情况,每个人都会抓狂。
我们曾经拿学习Scala跟迁移到新平台上(比如Python/Django 和 Ruby on
Rails)做过对比。用Scala的话,原先Java的知识大概有75%还能用得上。同样的库、同样的IDE、同样打jar包和war包的方式,运行时环境和特征都一样。优秀的Java程序员可以用一天实现学会用Scala编写Java风格的代码,然后再学会闭包和隐式类型转换的强大之处,很快就能比用
Java更有效率了。
InfoQ:
我听到人们对Scala最为诟病的是,这门语言太过复杂了。我觉得这些声音大多应该是由于Scala的可读性造成的:同样的代码,如果用更为严格一点的语言(比如Java)来写的话,就会比Scala更容易理解。你觉得这种批评合理么?你是怎么想的?
没错,可读性应该是代码最重要的品质。我不在乎代码到底是命令式的还是函数式的,我也不在乎它到底是合乎Scala的规范,还是只把它当作无分号的Java
来用,我只在乎它是不是好理解。在我们学到Scala新特性的时候,我们会根据代码是不是能够更明确的体现出实现意图来决定用不用。比如,我们试过
Scala的Either类来消除一些if表达式,但团队一致认为,if表达式更容易读懂,所以我们就没用Either类。
我承认,由于Java语法的严格,那些几行几行的代码看起来是容易懂,但是对于真正能用起来的代码来说,我觉得这根本不是问题。因为我不需要去理解实现细节,我想要理解的是代码意图。优秀的设计和OO技术可以增强Java代码的表现性,但我读Java代码的时候,仍然常常见木不见林。在表现代码意图的层次上,Scala突破了Java的很多限制。
举个例子来看,Content API需要判断到底是要以XML或JSON格式返回结果,还是重定向到HTML浏览器上。它可以接收一个字符串,其格式为
format=query,也可以接受一个.xml或是.json的扩展名,也可以从http
header的Accept字段里面读取扩展名类型。下面是实现代码,我觉得这可以很好的证明Scala强大的表现力(它会一步步调到Scala的
Option类): def negotiateFormatParameter =getParam("format"). orElse(getExtension). orElse(getExtensionFromAcceptHeader). getOrElse("html")
这同样也可以很好的证明,要说可读性这回事,最起码也得看看要读完多少代码才能搞明白一个功能。换成Java的话,就得写上很多跟问题域完全无关的代码,比如非空检查、getter/setter、用来做依赖注入的构造函数、操作容器。这些地方用Scala都可以写的很精炼。当然,你也可以说这类代码大部分都可以用IDE生成,但我还是得去读你写的构造函数和getter/setter啊,要不然我怎么知道你有没有在里面做什么其他处理
找个经典的例子来比较一下看看:
Java: public class WelcomeClass { private String name; public WelcomeClass(String name) { this.name = name; } public String sayHello() { return "Hello " + name; } } Scala: class WelcomeClass(name: String) { def sayHello = "Hello " + name }
Java 版的代码三次告诉我”name“是String类型,并且五次提到“name”。Scala版的代码只提到“name”两次,也只说了一遍”name“是
String类型。这虽然是个很简单的例子,但也能说明Scala的优势:少了格式约束,少了重复,也就少了树木多了森林,换句话说,读代码的人更容易看到实现意图而不是细节。
我也注意到,一行孤零零的Scala代码要稍微多花上一点时间才能明白它干了啥,但它急剧减少了代码行数,够本还有余呢。
InfoQ:
说到Scala的复杂性,你觉得这门语言的某些特性──我觉得这里主要是符号命名和隐式转换──会给真实应用带来麻烦么?
实际上隐式转换帮了我们很大忙。我前面说过,我们用SolrJ跟Solr通信,这是个很优秀的类库,但是它有Java库的通病──太喜欢返回null了。为了不让大量的非空检查污染了代码库,我们就把一些核心的类隐式转换成了别的类,而在新类里面就拥有一些Scala风格的方法。所以这个特性非但没有给我们在实际应用中带来麻烦,还帮我们解决了问题。另外值得一提的是,IntelliJ
Scala插件现在几乎可以理解所有的隐式转换了,所以如果你不明白到底发生了什么,control +
左键单击就能带你到发生调用的地方。
我们其实也在避免使用重量级的符号库,避免用符号来做方法名,但我觉得这是Scala的一个很重要的特性,也跟其他特性一样,都有可能被过度使用。有的时候这个特性很有用:我们有个方法从http请求中把用来做查询的字符串提取出来,这个方法名就是”?",放在代码里面很好理解。用Scala的时候,你得比用Java投入更多的精力来让别人更容易理解你的意图。能力越强,责任越大,说的就是这个意思。你不能因为这种力量容易被人误用就不想要它。
InfoQ: 人们对Scala企业应用的另一个关注点是,每一次Scala发行新版本总会破坏向后的兼容性,比如在Scala
2.8上编译的应用程序就没办法跟在之前的版本上编译出来的二进制文件一起用。你觉得这个问题严重么?你是怎么处理Scala项目之间兼容性问题的呢?
我们一开始用的是Scala
2.7.7,等2.8.0和2.8.1发布以后,就马上迁移过去了。这个过程很顺利,到2.8.0版本用了不到一天(这还只是因为我打算消除所有
deprecation的警告信息),然后又换到了2.8.1。我们用到的所有库都针对Scala的各个版本相应的发布过多个版本,所以这方面没出现问题。
唯一出问题的地方是我自己的项目,当时我用的是2.8预发行版。但人家已经明确表明这是预发行版了,我还要用,那就是我自己的事了。
我们现在打算用simple-build-tool来构建Scala,换掉Maven。前者能够更方便的针对Scala的不同版本发布内部使用的库。
我宁愿面对升级带来的不兼容,也不愿意看到在Java里面有些东西永远不曾变过,也永远无法改变。我们常用的
HttpServletRequest.getHeader方法到现在还是返回java.util.Enumeration,可Enumeration早在Java
1.2的时候就废除了。
InfoQ:
你现在招人做Scala开发的情况怎么样啊?目前找优秀的Scala程序员跟找Java程序员一样容易么?
我们的主要关注点在于招的是优秀的程序员,而不是专门招Scala程序员。我们希望找到热衷于通晓多门语言的web开发者,至少用过Groovy,或者是Scala、Clojure、Ruby、Python。这种人往往都会喜欢Scala开发的工作机会。
InfoQ: 现在guardian.co.uk一共有多少行Scala产品代码了?
guardian.co.uk每两周发布一次,它的核心代码在两周前还只有一个Scala类。我们之前一直有规定,在guardian.co.uk的代码库上不许写Scala代码。这是为了确保我们所有人都为迎接Scala做好了准备(也免得我总是动出重写的心思来)。
不过我们的microapps服务已经用Scala实现了,在它的驱动下,网站的很多组件也换成了Scala,包括Search(用Lift写的)、 Most Viewed、Punctuated
Equilibrium Mystery Bird,在每个页面上显示相关内容的组件也是Scala实现的。
另外,我们新开发的身份校验平台也是用Scala写的,它还在开发阶段,不过第一个版本已经上线了。
InfoQ: 你们打算将来继续用Scala么?
我们发现Scala可以以较少的代码量提升交付速度。这让我们团队重新焕发了生机。我们会继续挑选合适的工具工作,无论是Scala,还是Python、.NET、PHP、Bash。
过去的六个月里,我们新开的基于JVM的项目都用的是Scala,没有一个用Java。我们接下来的新项目肯定也不会用Java了,而且Java
7也没什么让人满意的新特性,发布时间又一拖再拖。
|