【发布时间】:2023-04-06 20:18:01
【问题描述】:
在我的 Scala 项目中,我有一个非常广泛和深入的类和包层次结构。显然我希望将包的依赖关系保持在最低限度。
我不知道我是否可以为此使用编译器, 所以我想知道如何使用单元测试来验证包的独立性?
PS:由于我使用的是 Scala,而不是 Java,因此该方法可能应该适用于字节码级别。
【问题讨论】:
标签: unit-testing scala dependencies
在我的 Scala 项目中,我有一个非常广泛和深入的类和包层次结构。显然我希望将包的依赖关系保持在最低限度。
我不知道我是否可以为此使用编译器, 所以我想知道如何使用单元测试来验证包的独立性?
PS:由于我使用的是 Scala,而不是 Java,因此该方法可能应该适用于字节码级别。
【问题讨论】:
标签: unit-testing scala dependencies
这不能通过单元测试来完成,但编译器是你的朋友。使用 private[PACKAGENAME] 使类仅在包内可见。与 Java 不同,该类在子包中也可见。
【讨论】:
我强烈推荐Classycle。它适用于我的混合 Scala/Java 项目。它在字节码级别工作,我从未遇到过与 Scala 相关的问题。
在小型项目中,您可以手动编写配置文件。我们的项目很大,所以我编写了一个 Scala 脚本来生成配置文件。生成每个包的文件部分如下所示:
[agent] = org.nlogo.agent.* excluding org.nlogo.agent.*.*
[agent+] = [agent] [api+]
[agent-] = org.nlogo.* excluding [agent+]
check [agent] independentOf [agent-]
这表示 org.nlogo.agent 可能依赖于 org.nlogo.api(并递归地依赖于 org.nlogo.api 允许的依赖项),但不依赖于其他包。
您还可以编写检查外部依赖项的规则,例如以下是我检查我们是否仅依赖某些特定包中的 JOGL 的方法:
[JOGL-free-zone] = org.nlogo.* excluding [gl.render] [gl.view]
[JOGL] = net.java.games.* javax.media.opengl.*
check [JOGL-free-zone] independentOf [JOGL]
【讨论】:
我玩过 JDepend ,但没有在愤怒中使用它。它允许您设置包和类依赖约束,并使用 JUnit 测试对其进行验证。它还具有大量功能,可用于查找依赖循环、计算大量指标,并通常保持您的架构干净、闪亮和新鲜。
【讨论】:
scala 编译器可以为您生成依赖关系图,然后您可以使用自制工具对其进行检查。你可以这样称呼它:
scalac -make:transitive -dependencyfile dep.txt *.scala
它会产生什么:
.;C:\Progra~2\Java\jre6\lib\ext\QTJava.zip;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip
-------
Aposta.scala -> Aposta.scala
Aposta.scala -> Premio.scala
Aposta.scala -> Bilhete.scala
Premio.scala -> Premio.scala
Premio.scala -> Sorteio.scala
Bilhete.scala -> Aposta.scala
Bilhete.scala -> Bilhete.scala
Bilhete.scala -> Sorteio.scala
Browser.scala -> Browser.scala
Megasena.scala -> Browser.scala
Megasena.scala -> Bilhete.scala
Megasena.scala -> Sorteio.scala
Megasena.scala -> Megasena.scala
Sorteio.scala -> Premio.scala
Sorteio.scala -> Sorteio.scala
-------
Aposta.scala -> megasena\Aposta$.class
Aposta.scala -> megasena\Aposta$$anonfun$1.class
Aposta.scala -> megasena\Aposta$$anonfun$toString$1.class
Aposta.scala -> megasena\Aposta$$anonfun$toString$2.class
Aposta.scala -> megasena\Aposta.class
Premio.scala -> megasena\Premio$.class
...
此外,sbt 会自动执行此操作(在目标目录中查找名为 analysis/dependencies 的文件以及 analysis/external)。这就是他们的样子:
#Source Dependencies
#Mon Jan 04 18:31:56 BRST 2010
Sorteio.scala=Megasena.scala;Premio.scala;Bilhete.scala
Premio.scala=Sorteio.scala;Aposta.scala
Browser.scala=Megasena.scala
Aposta.scala=Bilhete.scala
Bilhete.scala=Megasena.scala;Aposta.scala
Megasena.scala=
RedBlackTree.scala=
和
#External Dependencies
#Mon Jan 04 18:31:56 BRST 2010
C\:\\Workset\\megasena\\project\\boot\\scala-2.7.4\\lib\\scala-library.jar=Browser.scala;RedBlackTree.scala;Premio.scala
;Bilhete.scala;Sorteio.scala;Megasena.scala;Aposta.scala
C\:\\Arquivos\ de\ programas\\Java\\jdk1.6.0_16\\jre\\lib\\rt.jar=Browser.scala;RedBlackTree.scala;Premio.scala;Bilhete.
scala;Sorteio.scala;Megasena.scala;Aposta.scala
【讨论】: