如何从旧的Scala(sbt)项目高效地分支到Java开发

问题描述 投票:0回答:1

我目前正在接管旧的 Scala 应用程序,主要目标是用 Java 编写新功能,但利用旧的通用代码。到目前为止,存储库看起来或多或少像这样:

├──common-scala-module-1
│   ├── src
│   │   ├── scala
│   │   │   ├── **/*.scala
│   │   ├── test
│   │   │   ├── **/*.scala
├──common-scala-module-2
│   ├── src
│   │   ├── scala
│   │   │   ├── **/*.scala
│   │   ├── test
│   │   │   ├── **/*.scala
├──scala-module-3
│   ├── src
│   │   ├── scala
│   │   │   ├── **/*.scala
│   │   ├── test
│   │   │   ├── **/*.scala
├──scala-module-4
│   ├── src
│   │   ├── scala
│   │   │   ├── **/*.scala
│   │   ├── test
│   │   │   ├── **/*.scala
├── build.sbt
├── .gitignore
└── (other scala files that doesn't matter for this problem)

所有这 4 个都会生成 jar 模块,但对 生产 代码真正重要的模块来自

scala-module-3
scala-module-4
(取决于两个公共模块中的类)。我需要开始编写新代码(新模块,如
scala-module-3
),但从现在开始用 Java 编写。然而,如果出现这种需要,我仍然需要维护旧代码。我有两个主要问题,我想获得架构建议(我在问题后的括号中写下了我目前认为最好的路径):

  1. 我应该放弃这个存储库并为 Java 模块启动一个新的存储库吗? (我相信将它们分开是很有意义的:即使如果我将代码库留在一个存储库中,代码库应该可以很好地协同工作。IMO,因为我创建新模块而不是仅仅更改旧模块,这给了我很多理由添加jar 来自公共模块作为 Java 代码的依赖项,并仅保留旧存储库维护
  2. 我是否应该从 SBT 迁移到 Gradle/Maven?如果是:哪个以及为什么?答案是否会根据问题 1 的结果我将做什么而改变? (我在当前的所有项目中都使用了 Maven 和 Gradle,它们经过了现场测试,在管理构建和依赖项时会发挥很大作用,而且它们是 Java 项目中的标准,所以我倾向于 Maven。最后但不是至少:我不太了解SBT,这会让我额外头痛

注意:我确实在多个项目中拥有相当广泛的 Java 背景,并且我确实了解 Scala 基础知识(比如它利用 JVM 技术,并且即使我刚刚开始将 Java 代码突然放入存储库,SBT 也应该可以工作)。我只是在寻找架构建议,以便了解权衡并让我(也许有一天其他人)的生活更轻松,因为这个应用程序现在将 Scala 抛在了后面(除了错误/维护之外)。

java git scala architecture sbt
1个回答
0
投票

您的首要问题不是在 Maven 或 Gradle 之间进行选择。

您的主要问题是您不能在未来的 Java 代码中直接使用任何这些 Scala 依赖项(它编译为 JVM 字节码的事实并不重要,因为您不会用字节码编写未来的包)。

您无法直接使用任何这些依赖项的原因是:

  1. Scala 可以简单地表示 Java 的类型,而 Java 无法在不扭曲的情况下表示 Scala 类型系统中的几乎任何内容。
  2. Scala 可以轻松实例化所有 Java 的接口和类,而 Java 则很难实例化任何 Scala ADT 或访问伴生对象上的内容
  3. Java 中没有元编程机制,因此它无法使用
    implicit
    /
    given
    ,更不用说宏了。因此,暴露
    given
    就像在黑色的深渊中尖叫,却得不到任何回应,即毫无意义。

您可能尝试的一件合理的事情:

  1. 列出您希望 Java 代码依赖的所有子项目,即
    common-scala-module-1
    common-scala-module-2
  2. 对于每个子项目
    <P>
    ,创建额外的
    <P>-javaapi
    子项目,即
    common-scala-module-1-javaapi
    common-scala-module-2-javaapi
    等。
  3. 每个
    <P>-javaapi
    子项目内部:
    • 编写一个纯Java API,公开模块
      <P>
      提供的所有功能,但按照惯用的Java编写。支持
      FactoryFactories
      和一页又一页的重复泛型。
    • 使用
      <P>
    • 提供的功能在 Scala 中实现纯 Java API
    • 使用 SBT 构建
      <P>-javaapi
      -javaapi
      是一个混合的 Scala/Java 项目,因此可能更好地使用 SBT 构建它)
  4. 今后,请使用
    -javaapi
    包中的纯 Java API。

这应该有效,因为:

  • 您可能从 Java 使用的任何功能都可以通过纯 Java 类型和接口来表达,如果无论如何都无法使用它们,就没有理由泄漏任何 Scala 类型和隐式。
  • 在 Scala 中实现 Java 接口很简单
  • 通过
    scala.jdk.CollectionConverters
    等转换所有集合是微不足道的。
  • 使用 SBT 构建混合
    -javaapi
    包应该可以正常工作。

最后,您将获得一堆包

common-scala-module-1-javaapi
...
common-scala-module-N-javaapi
,它们不仅在字节码级别上几乎与任何 Java 包没有区别,而且在导出类型、接口和文档级别上也是如此。

除非你的代码是紧密耦合的混乱,导致你无法在没有

also
修改和重新运行所有非通用模块的情况下测试 common-scala-module-N,那么最好创建一个具有单独
java-module-0
 的单独存储库java-module-1
等并使用 Maven(或 Gradle)构建它们。

© www.soinside.com 2019 - 2024. All rights reserved.