I started using Scala 5 years ago instead of Java after starting (but never quite finishing) to read the first edition of Programming in Scala. First only present in tests, my first attempts at Scala code would quite soon invade small utility classes and before I knew it take over all of my projects.
There are many rants about Scala out there. This isn’t one of them. I’m not here to complain, but rather to applaud.
This post is intended for developers curious about Scala or have heard about it some time ago but never quite got to look more into it, put off by a feeling of “well this is a show-stopper for me”. If you’re a Scala aficionado you are of course welcome to read it and share it.
It consists of 3 parts:
- my favourite “killer features”
- debunking some of the Scala myths that still float around in the JVM community
- some advice for learning Scala
Let’s get started!
5 years without a NullPointerException
Well, almost. I have seen a few here and there but by no means can this handful of occurences be compared to the mountain of stacktraces leading to the infamous
java.lang.NullPointerException that was polluting my server logs and my life.
The mere thought of a `NullPointerException now upsets me, bringing back memories of all those hours wasted starring at a screen and wondering where I or another programmer had erred. To err is human and no progammer should ever be caned for forgetting about the nullability of a reference. It is the responsibility of the language to forgeo this unfortunate turn of events by offering in its design an alternative that will just work (like Apple products did a few years ago).
I am not going to elaborate on Scala’s design choices for eradicating the
NullPointerException (a combination of the
Option type and of first-class functions) but suffice it to say that if you stick to the following simple rules you are almost guaranteed not to see a
NullPointerException in your Scala code again.
- NPE erradication rule #1: never, ever, ever (ever!) initialize a variable with null. All potentially undefined state must be modelled by an
- NPE erradication rule #2: always treat the undefined case right from the beginning, don’t cheat by calling a rogue
geton an Option
- NPE erradication rule #3: when using a Java library wrap the results it provides in an
Option(unsafeJavaResult)because many libraries tend to sometimes, without so much of a warning, return
And if you use Scala and don’t follow these rules and are plagued by a myriad of
NullPointerException-s then you deserve it.
Empowered code organization
One class != one file
Scala does not care for how many classes you put in one file. And since those classes often happen to be orders of magnitude smaller than their Java counterparts, it is not uncommon to see many classes live in the same
.scala file. Doing the opposite would honestly just feel weird and be a waste of time. You still use packages in Scala but the hierarchies aren’t as deep and the left-hand file browser of your editor as crowded with files as in Java (if you use a file browser of sorts, that is).
No matter what kind of editor you are using, the interesting result of this possibility of organizing code is that entire logical constructs can be self-contained in one single file which can be scrolled back and forth, hence avoiding to jump from one file to another which at the end of the day is a form of context switch (and as we all know, context switch is evil).
Shrink, Hide and Embody
Scala makes it possible to apply John Maeda’s law of SHE (shrink, hide and embody), for example by nesting functions:
someComplexFunction nobody cares about
anotherStep (they are not being reused) so no need to pollute the class with them. By allowing to nest functions it is possible to reduce complexity and at the same time to contextualize intermediary steps of one function. Or in other words: when reading a class, I want to be able to focus on the big picture and not have to use an additional mental effort in order to filter out the noise.
This mechanism is much more powerful than the convention of placing “smaller” functions towards the end of a class and prepending them with the
private keyword, since doing so still does not solve the problem of contextualizing - you still need to look around or use your IDE’s “where is this function being used?” feature in order to relate one function to another.
Traits for good and not for evil
One of the myths surrounding Scala is that by allowing for “multiple inheritance” it opens a pandora box which will almost certainly doom any large enough project. In practice I have seen very few deep class hierarchies in Scala projects. Traits are often used as a tool for composing related code. A neat example can be found in the Play Framework:
A controller in an MVC application has many concerns to deal with. All the types above (starting with
Results) are traits that cover one of those concerns (in the original source code this is all in one line, but on this blog this wouldn’t read very nicely).
case classes or the Swiss army knife of Scala
case classes are arguably the killer feature of the Scala language, especially when coming from POJO-land. Case in point:
I now get for free:
- a constructor taking at least two parameters and that can be called with named parameters
- getters for x, y and z
- a method for creating immutable copies of immutable instances
And just look at this REPL session (more on the Read Eval Print Loop later):
The members of a case class are immutable, because immutability is the future. They are so quick to define it makes your head spin. And yes, Java IDEs can generate all the getters, constructors, and so on with the simultaneous stroke of 3 keys. But let’s be honest: that’s all just noise that makes it harder to focus on solving a business problem.
And even more
Truth be told, I haven’t written Java in what seems like a very long time. Which is why it is easy to forget about some of the little things that makes writing Scala code more enjoyable than Java one: no need for semicolons, type inference, tuples, pattern matching, etc…
Here is a good overview of the most annoying things one quickly misses when coming back to Java from Scala.
Debunking some Scala myths
“There is no good IDE support for Scala”
When I started using Scala on a regular basis, IntelliJ IDEA was the only IDE that had any kind of support for the language that went beyond simple syntax highlighting. On my old MacBook Pro it crashed every 10 minutes and the presentation compiler kept giving me false positives. I got used to the having to restart the IDE every 10 minutes and learned to differentiate “working broken code” from “really broken code”, only trusting sbt and the Scala compiler.
Things are much better now and unless you are doing crazy type gymnastics IDEA is well on top of things when it comes to Scala projects. Eclipse picked up with the Scala IDE and I think others have followed as well. The ENSIME project provides support for many different text editors (emacs, vim, sublime, atom) and there is good support for Atom.
“Scala has so many complex features, novice developers have a hard time getting up to speed”
One of the criticisms of Scala is that it has all those language features that are complicated to understand and that make it hard for novice Scala developers to join an existing Scala project or to work with it in a team. I would argue that this has much less to do with the Scala language itself than with the architectural choices made by the people building the project.
It is hard to find the right balance between shipping features and building a maintainable code base, a “tech lead” (or whatever you want to call the role) has to keep an eye on quite a few things at once. In my experience reducing the usage of fancy libraries and exotic language features and to enforce a consistent way of doing things is key to building a maintainable codebase with many people involved. Of course you need to have a firm grasp on the language and the tooling itself in order to tell apart “useful” from “fancy” and “exotic”. If everyone on the team is new to the language and platform you’re in for an interesting ride.
Technological barriers can easily be found in any language or platform, even Java. Given enough load-time weaving, bytecode modification, proxies etc. promoted by annotations a newcomer will have a hard time grasping the “magic” and run into trouble. I’m currently working on a project that has one of its systems written in Grails, and the GORM (Grails ORM, i.e. Grails on top of Spring on top of Hibernate) is confusing everyone.
To the contrary I would argue that Scala projects are easier on newcomers because there is a general consensus to avoid doing things at runtime, meaning that newcomers can count on the compiler telling them where their code is wrong, rather than having to walk through incredibly long stacktraces, often not understanding what is really going on.
“The sbt build tool is a jungle of weird-looking arrows”
The build tool sbt has seen an amazing evolution over the past years. It used to be a rather frustrating experience to work with it, especially on larger code bases, where dependency resolution would take eons. Luckily sbt rolled its own dependency resolution engine which fixes this really annoying issue.
When it comes to the weird-looking syntax sbt build files used to have things got much better as well. Heck, I can’t even find some of the funny arrows in my current project build files to show off here. And if you want to dive into the depths of SBT there is now a book about it
“The Scala compiler is sooo sloooow. Let me show you that XKCD comic to make fun of it”
No, I’m not going to display this XKCD comic here: since I have switched to a MacBook Pro Late 2013, compilation time is not an issue anymore. The compiler itself has gotten faster and sbt has good support for incremental compilation now. Of course it is still slower than Java, but it isn’t anymore the kind of slow that impacts productivity during development. Initializing all those Spring Beans or whatever it is that happens when a Java project starts these days (I’m really out of the loop here) takes much longer.
“I can throw all of my object-orientation knowledge out of the window”
Scala being a functional programming language does not mean that all the good parts of object-oriented programming should be discarded. To the contrary, since Scala is also a full-blown object-oriented language, all the good parts of OO can be used as well - and these are not mutually exclusive.
I have seen novice Scala developers get so much functional fever that they forget about the Open-Closed-Principle, cramming functions in
object-s (Scala’s equivalent of
static) and hard-wiring these all over the place, undermining the testability of the code.
“I need to become a mathematician and know all about Monads before I can get started”
Ok, so this is a myth we have to blame the militant functional wing of the Scala community for (I mean I am sure they mean well, but it’s easy to scare people off with it). Don’t let yourself be lurred into reading one Monad tutorial after another, tutorial after another, trying to wrap your head around endofunctors and whatsonot. Unless you are a mathematician and you eat monads with maple syrup for breakfast, of course (I heard that that’s a thing).
But seriously now: don’t let yourself be scared off by “category type theory” and other fancy-sounding words. You do not need all of this theoretical background in order to learn and become a fluent Scala developer. I know, because I have not bothered to look at those things until 4 years with the language. And when I did it’s not like I had an epyhpany, throwing out all the code I had written until then. In fact, I was monading all over the place, just had no idea how the things I was building and using were called.
In the end, these are just words.
Advice for learning Scala
If you want to learn Scala, you have to be ready to want to learn a new language.
I think much of the early criticism Scala got in the Java community was unfair and in part due to many Java developers never bothering to learn another language than Java, staying quite comfortably within the bounds of that language and not venturing outside of that well-defined space. From that perspective, any other language is going to look evil.
To break the “language bareer” this book is quite interesting.
Get a book
When I started learning Scala, I first had a look at what is possible in the Programming in Scala book, which turned out to be a bit too long and detailed, so I skipped a big part and read Programming Scala which turned out to work quite nicely for me.
And if the thought of reading a whole book puts you off you can always download Scala by example PDF.
Get a project
Let’s be honest, learning a new programming language requires work. It is much easier to have a purpose beyond learning the language such as a small project. It’s like learning a new (spoken) language, really: you will learn it much faster if you travel to and live a bit in the language’s country.
I found that many people started to learn Scala after starting a project with the Play Framework. This should come to no surprise - web frameworks, and the Play Framework is no exception, act as a gateway drug to a new programming language. What’s interesting then is that Play has both APIs in Java and Scala, so you can slowly transition from one to the other (provided that you architect your application correctly especially in terms of database access).
Use the force REPL
Before even getting started with working in an IDE, exploring Scala through the REPL (Read Eval Print Loop) makes things very easy. It is possible to copy-paste code snippets from websites into the REPL and evaluate them in their entirety. The REPL also has code completion built-in (by pressing the tab key) which makes it possible to explore a type. I highly recommend installing Scala and playing with it!
You don’t have to start all functional
Don’t put too much pressure on you. The advice that is outlined in the third chapter of Reactive Web Applications is to start imperative and to slowly transition to immutable, declarative code.
Take your time to get familiar with the syntax and only then start working on the paradigm shift. You will have a much nicer experience if you are comfortable enough with the syntax to know how to fall back to an imperative programming style if the declarative one doesn’t suit you just yet.
Don’t try too many new things at once
It is tempting to start working with many of Scala’s features at once: implicit parameters, implicit conversions, traits, infix notations, functions, higher-order functions, lazy values as well as all the features related to type-level programming to name but a few. But you don’t have to and in fact you may be better of to take one step at the time.
That’s it for this recap. I hope I managed to convince you that Scala is not evil after all and wish you much fun with it!