Миграция 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 с прямым переводом, вы можете обнаружить, что то, что вы тестируете, не то, что вы тестировали раньше. При выполнении миграции важно, чтобы вы сохраняли смысл кода вместе с тестами, а не допускали фрагментацию мысли.