29

What are the most important points to be aware of, and the workarounds, when gradually migrating an existing Java codebase to Scala? With a (potentially very long) intermediate phase where both languages are in use.

The sort of things I'm thinking about are:

  • different collection hierarchies
  • Java constructs that Scala can't handle well
  • Scala constructs that are impractical to use in Java
  • build tools
  • compilation order
  • immutability support in frameworks
  • etc.
Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
Kevin Wright
  • 49,540
  • 9
  • 105
  • 155
  • 3
    Don't do this, if it is already big working code. Scala doesn't like many java futures and vice versa. Old,big, *tested* application is not worth the work you will need to do. – baklarz2048 Oct 19 '10 at 12:18
  • All the answers here *will* be relevant to anyone seeking to add new Scala code to an existing Java codebase. Inevitably, there will be some conversion of existing code to help out here. In general though, I agree, no need to change something that isn't broken or otherwise causing you problems. – Kevin Wright Oct 19 '10 at 12:27
  • The thing I can immediately think of relates to whatever types of tests you currently have, as it seems likely you'd change the core code first using the tests to prevent regressions. Can those tests be kept the same when migrating? Or will it require changing both simultaneously and potentially introducing bugs? – Sean Parsons Oct 19 '10 at 11:14
  • Scala supports mixed-source projects quite well, so you can convert one class at a time and keep your test suite running throughout the entire conversion process. See the [maven plugin](http://scala-tools.org/mvnsites/maven-scala-plugin/usage_java.html) and [sbt](http://code.google.com/p/simple-build-tool/wiki/JavaSources) docs on setting that up. – David Winslow Oct 19 '10 at 11:46
  • As with any other behaviour change, tests should also be updated to reflect this. It may even make sense to migrate tests first, so that you're certain to understand exactly how the code works. – Kevin Wright Oct 19 '10 at 11:55

5 Answers5

28

Scala doesn't like:

  • inner Java classes
  • static methods and variables (especially in super classes)
  • raw types

Java doesn't like:

  • Scala objects traits
  • closures
  • actors (except Scarlett Johansson and Akka Actors since they have a Java API)
  • implicits, especially Manifests
  • advanced type constructs (higher kinded types, structural types, abstract type vars)
Viktor Klang
  • 26,479
  • 7
  • 51
  • 68
Landei
  • 54,104
  • 13
  • 100
  • 195
8

Initially (i.e. the first phase of migration), I would say that you don't want to export an API (interface/public method etc) with a hard-to-use-from-Java scala construct.

In practice I would limit this to exporting anything which is scala-specific (again, I'm talking about the first phase of migration here):

  • scala library classes (function types, collections etc)
  • higher-kinded generic type signatures
  • implicits

So what does that leave? Well, the internals of classes (private methods, fields etc) can be converted to use scala constructs and library classes.

If you have any APIs (especially client-facing APIs which you intend to migrate), I would design them anew from the ground up in Scala; initially using a Java back-end. Then I would slowly eat away at the code inbetween.

Of the points you have highlighted, I would agree that the immutable paradigm of Scala and the mutable paradigm of Java do not mix well. The other points I have found less problematic.

Another main point of paradigm-mismatch is how to convert any concurrent code you have (i.e. that which makes use of java.util.concurrent). This can, of course, be converted as is but the question is whether to replace the concurrency model based around locking with one based around actors or STM. In either case, this is also likely to be a complete redesign, as opposed to a conversion per se.

oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
8

A nice presentation that may give some insights on subject is Sneaking Scala Into Your Organization by David Copeland.

pedrofurla
  • 12,763
  • 1
  • 38
  • 49
3

One trick I like to use, I'll define an object using idiomatic Scala properties (vals and vars), then add the @BeanProperty annotation to expose then as JavaBean properties. That way, each language can use the native idioms.

The @BeanInfo annotation can also be used at a class level for a similar purpose, but you have to be careful here - When using @BeanInfo, any methods that you additionally custom-define as setXXX or getXXX won't be exposed via bean introspection. This is important, as you have to manually write getters/setters for collection types if you also want to handle translation between e.g. Scala Lists and Java Lists.

Kevin Wright
  • 49,540
  • 9
  • 105
  • 155
1

I'll add to what others have said since they're correct and meaningful. More than just the code, you'll need to bring over your unit tests. This doesn't sound hard until you start changing mutability and threading constructs while still attempting to have everything work the same way as it did before. During the transition it's very important to keep all the edge cases in mind while discovering additional edge cases you may introduce during the migration.

If you bring your unit tests into a good Scala testing framework like ScalaTest with a direct translation you may find that what you are testing is not what you were testing before. While making your migration it's important that you keep the intent of the code together with the tests instead of allowing fragmentation of thought.

wheaties
  • 35,646
  • 15
  • 94
  • 131