Getting Into Scala
By Adrian Sutton
When I was in Australia visiting Ephox’s awesome engineering team recently, it was suggested that we should be seriously looking at using Scala for some or all of the server side development we have coming up. The key benefit that was described to me was based on productivity – I certainly think that has merit but I’m somewhat more interested in it being a potential solution to the new cross platform problem1{#footlink1:1255615173985.footnote}. Options like JRuby and Jython are also a possibility in this space, but Scala fits more nicely into a Java programmers mind-set and is designed with the JVM in mind, so while it pushes a lot of boundaries, ultimately it fits with the JVM and Java very nicely2{#footlink2:1255615348893.footnote}.
So I read through the O’Reilly Programming Scala book on the plane ride home3{#footlink3:1255615446418.footnote}, then jumped in and built a small but real-world project with Scala and integrated it into a Java servlet project. I think it’s given me a pretty good grounding in what Scala can do, the benefits it brings and the general state of play.
The Language
The Scala language is fantastic. Easy to learn if you have a solid programming background and just a smidgeon of functional programming knowledge4{#footlink4:1255615598614.footnote}. I’ve always been on the fence between compile time and runtime typing, but I think Scala strikes the perfect balance. It’s strictly typed at compile time, but uses a lot of inference so you don’t have to constantly declare types. I quickly came to find that there are two places where it’s incredibly handy to always specify types:
- Parameters. Scala requires it anyway, but it is vital documentation for anyone who wants to call that method.
- Return types. Not usually required by Scala, but by being explicit you can catch quite a lot of weird errors that crop up and isolate them to the right method. If you leave the return type as inferred, the compile error you get usually comes out on the caller of a method and can be somewhat confusing. The most common error here is effectively not returning something or returning two different types by accident (usually because you expected a different return type from a method you called). This isn’t hard and fast – short, simple methods are usually best left inferred.
Having closures is definitely handy, but the benefit isn’t really in closures themselves. What really makes a difference is the libraries designed to be used with closures5{#footlink5:1255616107622.footnote}, and the functional programming style that comes naturally in Scala. Looking back at the code I’ve written, the structure really looks like something that would make sense as a mathematical equation – each method does one thing, consistently and without side-effects. More importantly though, the breakdown of methods that results winds up being quite logical and helps reusability a lot. I find that getting the split points for methods right in Java is much harder and requires more conscious thought.
Traits – wow do I ever love these things. The first key benefit I found for them was unit testing. In Java, one class would tend to be responsible for loading and processing it’s data. In Scala, traits make it so easy for the class to declare an abstract variable for the data and just provide the processing. Traits then step in to provide the loading part and provide a concrete implementation of the variable. It becomes obvious to have a LoadFromDatabase trait, a HardCodedString trait or a LoadFromFile trait – now where the data comes from is clearly separated. In tests you just use a HardCodedString trait and there’s no need for Mocks or Stubs.
Interestingly, there is a wonderful synergy between traits and JNDI. Traits can’t accept constructor arguments and even if they could it’s ideal to just declare that you want a new Widget() with DatabaseLoading and have it just work. JNDI gives you that ability – the DatabaseLoading trait just grabs the datasource from JNDI and there’s no need to tunnel parameters through to it like you would otherwise.
I’m also a big fan of the uniform access principle that Scala uses. Essentially, from the caller’s perspective, there is no visible difference between accessing a public variable and accessing a public method. So you can have a base class that declares an abstract variable, then implement it with a concrete method in a subclass and visa-versa. It’s an incredibly simple concept that gives a lot of flexibility and avoids a ton of boilerplate code.
The Tools
This is the weak point of Scala, but it shows some promise.
Testing Libraries
There are actually quite a few testing libraries in Scala – all of them somewhat difficult to get working inside an IDE or Ant build, but all quite solid and stable if you use their test runners. The xUnit equivalent is ScalaTest, I never got it working with Ant or Eclipse so gave up and moved on to Specs. I love it6{#footlink6:1255617559659.footnote}. The Aussie dev team recently switched from CamelCase test method names to using underscores7{#footlink7:1255617589258.footnote} for readability, but Specs takes that a few steps further by letting you use strings. For example:
“Administrator users” should { “have a password at least 8 characters long” in { …code goes here… } “be in the admin group” in { …code goes here… } }
The test output is really easy to read using the Specs runner, but it gets much less readable when using JUnit to run the tests via ant. You can avoid the outer ‘should’ block which helps readability in JUnit but it’s still not great. Fortunately, IntelliJ has support for Specs directly and lays things out pretty well, plus the normal runner isn’t bad.
Standard Toolchain
The Scala distribution comes with a good set of tools. A scala command for executing scripts and scalac for compiling classes are the main two. Both work really nicely and the scala tool is particular good for experimenting with things – especially when you’re trying to learn the type inference system.
The single biggest drawback is that scalac can’t compile Java code, so you can either have Scala code depending on Java code or Java code depending on Scala code, but can’t do both easily. This isn’t all bad, as it really encourages you to break the project down into independent libraries and reduce coupling but it would be nice to more easily mix languages.
IDEs
Wow, these are terrible. The Eclipse plugin is incredibly buggy and is practically unusable. NetBeans seemed to work well but is very short on features. IntelliJ has a good set of features but has overall stability issues since you need to use an early access build of the IDE – the plugin itself seems quite stable. IntelliJ also has some support for Specs and ScalaTest rather than having to run them through JUnit which is quite nice, but it didn’t seem able to just find all the tests in my project and run them – it was limited to one package at a time. Getting Scala working in IntelliJ is an absolute nightmare and you’ll spend forever searching Google for answers. There are magic libraries you need to put in place and very cryptic error messages if you don’t have them – at least it’s a once off. Once the Scala plugin works with a released version of IntelliJ I think that will be the winner, otherwise I may have to deal with NetBeans8{#footlink8:1255618541437.footnote}.
Java Libraries
They work really nicely, except that Scala doesn’t use the normal java.util Collections framework. Scala has it’s own collections framework with equivalents and they are dramatically better but it does make it difficult to inter-operate with Java libraries that use Java Collections. Fortunately, Scala provides wrappers for the Java Collection types to make them act like Scala collections, but it doesn’t have wrappers for going the other way. It’s definitely not the end of the world, but does make you think a bit more about where the Java to Scala leap should be – sometimes writing a few key classes in Java can make things dramatically easier. Judicious use of implicit conversions, a scary but powerful feature of Scala, can be a big help too.
I do like the ability to specify values in Scala as @BeanProperty and have the compiler automatically generate JavaBean compliant getters and setters (or just getters if it’s a read-only value as is common in Scala).
There can also be problems with tools that manipulate bytecode since the bytecode Scala generates is compliant with the JVM specs, but often quite different to what javac would product.
The Performance
I can’t tell the difference between Java code and Scala code. That’s roughly what other people are saying too. There are an awful lot of classes that come out of Scala code because of all the closures and traits and the like so it’s not going to work if you are tight on space such as in applets. Server side where processes are long-running and JAR size isn’t a critical concern, it will work perfectly. I would guess9{#footlink9:1255619251560.footnote}, that there are a very large number of short-lived objects being created and discarded with Scala due to the use of implicit conversions and all those closures, but garbage collectors are so heavily optimised for that use case that I can’t see any evidence that it makes a difference and the performance testing I’ve read about bears that out.
The Scala compiler implements tail-recursive optimisation and even supports an annotation so that you can mark a method as tail-recursive and get a compile error if it’s not.
In terms of scalability – Scala advocates claim that functional programming and immutable data structures that are heavily used in Scala are a key tool, if not the solution, for scalability. I don’t know and don’t really care – the applications I’m likely to write will fit nicely into the “scale by handling many requests at once” model rather than having to break up the work of each individual request over multiple threads. The problem will come in the database or web server level, not my application code. I’m watching Tim Bray’s Concur.next series with interest though.
Overall
Scala is very much a tool I’m glad to now have in my toolkit. It’s not yet ready for prime time purely because of the poor IDE support, but it is excruciatingly close. I can see me advocating it’s use in Ephox quite heavily if it deploys to .NET smoothly as the cross-deployment is a massive benefit and would be worth the pain of sorting out the tooling, but it would be hard to justify if that isn’t viable yet – especially given the potential for Ruby or Python to work on both J2EE and .NET.
I don’t think it will be long before the Scala toolsets catch up and it becomes an extremely compelling option for Java server-side development.
1 – it remains to be seen how stable/useful the .NET version of Scala is – I’ve been focussed on the Java side of things for now ↩
2 – this adds to the scepticism around the .NET version until I find time to really test it out though ↩
3 – yay for power points in cattle-class ↩
4 – a few months of Haskell in uni counts if you paid attention. In fact, Haskell is a particularly useful background to have as it is a very pure functional language and uses a similar static typing with inference system as Scala does. ↩
5 – thus I question how useful closures would be in Java ↩
6 – Actually, I think ScalaTest can do the same style of tests but I got Specs working first. ↩
8 – I love the concept of it’s ant based build system, yet somehow the implementation drives me nuts every time I try to use it ↩
9 – I’m too lazy to profile this at the moment ↩