Many modern software engineers now work on multiple projects over the course of their career, each with different requirements. These requirements often cause us to consider different tools and even languages to get our work done faster and more efficiently. The Commerce Order Processing and Order Details team decided to take a different approach and decided to integrate multiple languages into its development environment, using Java and the JVM as a base.
The Transition to Groovy
Java is a great language. It’s well supported, it’s standard in many large corporate enterprises, it’s taught in virtually every single CS/CE program so you have a large pool of talent to draw from. It allows you to create highly structured programs, and allows code reuse to a large extent.
But sometimes Java is frustratingly inflexible. Some code that should be dead simple is very complicated by virtue of forcing you down a particular philosophy. Worse, experienced Java developers tend to create designs that encourage complication and lots of structure. For a team that wants to be more flexible and agile, this is not good. Java 8 has created some mechanisms designed to address some of these, but they are in the very early stages.
The Order Details team at Ticketmaster wanted to experiment with design philosophies to encourage faster development and more flexibility; however, we had a large code base that we needed to add features to and we didn’t want to rewrite most of this code. So instead, we decided to test something out – introducing a language that wouldn’t be as verbose as Java. Enter Groovy.
Groovy is a language that compiles to the Java Virtual Machine. Its syntax builds on top of Java, which makes it very good as a transitional language – you rename a file’s extension from .java to .groovy, and it just works. Groovy has a lot of features that make it attractive: true closures, automatic field access, syntactic sugar to compact code, etc.
This isn’t possible without the JVM itself, which in itself allows you to use multiple languages in the same program.
Add in some Clojure
We needed to add a feature to our Order Details service that involved custom data translation. The details for that will be in a future blog entry, but eventually we decided to use Clojure as our implementation language, as it’s naturally suited to this type of feature. A similar feature that existed in one of the older versions of our service was 1-2 orders of magnitude larger in terms of lines of code, so we were motivated to make this change.
However, Clojure as a language is also a more difficult language to adapt. To help ease the transition, the members of our team decided to read documentation and books on the subject; we also used pair programming heavily to spread information through the team quickly.
It took around 1-2 months to finish the feature; however, the schemas to create the translations were easy to understand, and by and large the engine needs very little modification once it was written, so it was effective.
Advantages to the Approach
The main advantage in this approach is that you can write code that is particularly efficient for a particular problem without having to throw out existing code. The Clojure code, when written in Java, would have been several times larger and much harder to debug. In addition, if we needed something that was better to do in Groovy, we wrote it in Groovy. This included unit and integration tests, which is not well supported in Clojure. The Groovy change allowed us to slowly transition into a language that allowed us to move faster without having to slow down and learn an entirely new language.
Disadvantages to the Approach
However, languages need to be supported and new team members (whether they’re new hires or other teams working with our code base) need more time to ramp up to the code, especially if they’re from a mainly Java background. We decided the code for the feature was isolated enough that the transition can be done over time, but it’s still an issue.
In addition, there are certain architectural problems you won’t be able to solve with solely a language change. In that case, it may be better to start from scratch.
Who should use this approach and why would they benefit?
I don’t think this approach should be used for all teams; but teams with the characteristics below could be well served by this approach:
- A high degree of autonomy and engineers who understand multiple languages
- A domain-specific problem set better suited with another language
- An experimental approach to target a specific technology without leaving their current development environment