Миграция Java в Scala

Каковы наиболее важные моменты, которые следует знать, и обходные пути при постепенной миграции существующей кодовой базы Java в Scala? С (потенциально очень длительной) промежуточной фазой, где используются оба языка.

Вот о чем я думаю:

  • разные иерархии коллекций
  • Java-конструкции, с которыми Scala не справляется
  • Конструкции Scala, которые нецелесообразно использовать в Java
  • инструменты для сборки
  • порядок компиляции
  • поддержка неизменяемости в рамках
  • и т.п.

5 ответов

Решение

Скала не любит:

  • внутренние классы Java
  • статические методы и переменные (особенно в суперклассах)
  • сырые виды

Java не любит:

  • Черты объектов Scala
  • укупорочные
  • актеры (кроме Скарлетт Йоханссон и Актер Акка, так как у них есть Java API)
  • последствия, особенно манифесты
  • сложные типы конструкций (типы с более высоким родом, структурные типы, переменные абстрактного типа)

Хорошая презентация, которая может дать некоторое представление об этой теме, - " Sneaking Scala Into Your Organization " Дэвида Коупленда.

Первоначально (т. Е. На первом этапе миграции) я бы сказал, что вы не хотите экспортировать API (интерфейс / публичный метод и т. Д.) С трудной в использовании конструкцией скалы из Java.

На практике я бы ограничил это экспортом чего-либо специфичного для scala (опять же, я говорю о первом этапе миграции здесь):

  • классы библиотеки scala (типы функций, коллекции и т. д.)
  • сигнатуры родового типа с более высоким родом
  • implicits

Так, что это оставляет? Что ж, внутренние компоненты классов (частные методы, поля и т. Д.) Могут быть преобразованы для использования конструкций scala и библиотечных классов.

Если у вас есть какие-либо API (особенно API-интерфейсы, ориентированные на клиента, которые вы собираетесь мигрировать), я бы разработал их заново с нуля в Scala; изначально используя Java-сервер. Тогда я бы медленно поедал код между ними.

Из пунктов, которые вы подчеркнули, я бы согласился с тем, что неизменная парадигма Scala и изменчивая парадигма Java плохо сочетаются. Другие пункты я нашел менее проблематичным.

Другой основной момент несоответствия парадигмы - как конвертировать любой имеющийся у вас параллельный код (т. Е. Тот, который использует java.util.concurrent). Это, конечно, можно конвертировать как есть, но вопрос в том, стоит ли заменить модель параллелизма, основанную на блокировке, моделью, основанной на актерах или STM. В любом случае, это также может быть полная модернизация, в отличие от конверсии как таковой.

Один прием, который мне нравится использовать, я определю объект, используя идиоматические свойства Scala (vals и vars), затем добавлю @BeanProperty аннотация, чтобы затем выставить как свойства JavaBean. Таким образом, каждый язык может использовать нативные идиомы.

@BeanInfo аннотацию также можно использовать на уровне класса для аналогичной цели, но здесь вы должны быть осторожны - при использовании @BeanInfo любые методы, которые вы дополнительно определяете как setXXX или getXXX, не будут представлены посредством внутреннего анализа bean-компонента. Это важно, так как вы должны вручную писать методы получения / установки для типов коллекций, если вы также хотите обрабатывать перевод между, например, списками Scala и списками Java.

Я добавлю к тому, что сказали другие, так как они правильные и значимые. Больше, чем просто код, вам нужно перенести свои модульные тесты. Это не кажется сложным, пока вы не начнете изменять изменчивость и многопоточность, при этом пытаясь заставить все работать так же, как и раньше. Во время перехода очень важно помнить все пограничные случаи при обнаружении дополнительных пограничных случаев, которые вы можете ввести во время миграции.

Если вы перенесете свои модульные тесты в хорошую среду тестирования Scala, такую ​​как ScalaTest с прямым переводом, вы можете обнаружить, что то, что вы тестируете, не то, что вы тестировали раньше. При выполнении миграции важно, чтобы вы сохраняли смысл кода вместе с тестами, а не допускали фрагментацию мысли.

Другие вопросы по тегам