在将现有的 Java 代码库逐步迁移到 Scala 时,需要注意哪些最重要的点以及解决方法?使用两种语言的(可能很长)中间阶段。
我正在考虑的事情是:
- 不同的集合层次结构
- Scala 不能很好处理的 Java 结构
- 在 Java 中使用不切实际的 Scala 结构
- 构建工具
- 编译顺序
- 框架中的不变性支持
- 等等
在将现有的 Java 代码库逐步迁移到 Scala 时,需要注意哪些最重要的点以及解决方法?使用两种语言的(可能很长)中间阶段。
我正在考虑的事情是:
Scala 不喜欢:
Java 不喜欢:
最初(即迁移的第一阶段),我会说您不想使用难以使用的 Java scala 构造导出 API(接口/公共方法等)。
在实践中,我会将其限制为导出任何特定于 scala 的内容(再次,我在这里谈论的是迁移的第一阶段):
那剩下什么?好吧,类的内部(私有方法、字段等)可以转换为使用 scala 构造和库类。
如果您有任何 API(尤其是您打算迁移的面向客户端的 API),我会在 Scala 中重新设计它们;最初使用 Java 后端。然后我会慢慢吃掉中间的代码。
在您强调的几点中,我同意Scala的不可变范式和 Java 的可变范式不能很好地混合。我发现其他几点问题较少。
范式不匹配的另一个要点是如何转换您拥有的任何并发代码(即使用java.util.concurrent
. 当然,这可以按原样转换,但问题是是否将基于锁定的并发模型替换为基于参与者或STM的并发模型。在任何一种情况下,这也可能是一个完整的重新设计,而不是转换本身。
David Copeland的《 Sneaking Scala Into Your Organization 》是一个很好的演讲,可以提供一些关于该主题的见解。
我喜欢使用一个技巧,我将使用惯用的 Scala 属性(vals 和 vars)定义一个对象,然后添加@BeanProperty
注释以公开为 JavaBean 属性。这样,每种语言都可以使用本地习语。
注释也可以在@BeanInfo
类级别用于类似目的,但您必须在这里小心 - 使用 @BeanInfo 时,您另外自定义定义为 setXXX 或 getXXX 的任何方法都不会通过 bean 自省公开。这很重要,因为如果您还想处理 Scala 列表和 Java 列表之间的转换,则必须手动为集合类型编写 getter/setter。
我会补充其他人所说的话,因为它们是正确且有意义的。不仅仅是代码,您还需要带来单元测试。这听起来并不难,直到您开始更改可变性和线程结构,同时仍然尝试让一切都以与以前相同的方式工作。在过渡期间,记住所有边缘情况非常重要,同时发现您可能在迁移期间引入的其他边缘情况。
如果您将单元测试带入一个好的 Scala 测试框架(如 ScalaTest)并直接翻译,您可能会发现您正在测试的内容与您之前测试的内容不同。在进行迁移时,重要的是要将代码的意图与测试保持在一起,而不是让思维碎片化。