Page 126 - 《软件学报》2025年第7期
P. 126

孙伟杰 等: Java 依赖异味的实证研究与统一检测技术                                                    3047


                 Gradle 时都可能出现. 接下来, 我们将给出异味         1.1–1.8  的定义. 由于篇幅限制, 我们对最后的       3  类异味  (即  1.6–1.8)
                 将给出详细介绍      (包括例子分析; 而其他类别异味的详细介绍和例子分析参见附录                     A), 它们都是先前研究未涉及
                 或未充分讨论的, 并且分别对应了不同的构建工具.
                    (1) 类别  1.1 内外类名冲突: 模块与依赖库中包含完全限定名相同的类                 (2/47). 模块源代码中的类与模块所使
                 用的依赖库中的类完全限定名相同.
                    (2) 类别  1.2 外部类名冲突: 模块的依赖库之间包含完全限定名相同的类                  (7/47). 模块所使用的依赖库之间包
                 含完全限定名相同的类.
                    (3) 类别  1.3 库版本冲突: 模块的依赖树中存在同一依赖库的不同版本                 (7/47). 模块的依赖树中存在组织名和
                 构件名都相同但版本不同的依赖库.
                    (4) 类别  1.4 未声明依赖: 模块直接使用了未在配置文件中声明的依赖库                  (6/47). 模块源代码中使用某依赖库
                 中的类, 但此依赖库并未在项目的配置文件中得到明确声明.
                    (5) 类别  1.5 未使用依赖: 模块在配置文件中声明的依赖库实际上并未被使用                    (6/47). 模块源代码中并未使用
                 某依赖库中的任何类, 但此依赖库却在配置文件中声明.
                    (6) 类别  1.6 依赖范围误用: 依赖库的实际依赖范围与预期依赖范围不一致                  (12/47). 依赖库在配置文件中的依
                 赖范围, 也即实际依赖范围, 与其在模块中的真实使用场景所对应的预期依赖范围不一致. 在图                                 3(a) 对应的
                 #CNNIP-4 [32] 中, 项目  Cavisson-ns-nd-integration-plugin  在声明依赖库  jenkins-ci:jenkins-test-harness:2.25  时未指定
                 其依赖范围, 导致     Maven  自动将其依赖范围设置为默认的          compile. 然而  jenkins-test-harness 事实上是一个与测试
                 相关的依赖库, 应该仅在测试阶段使用, 因此其预期范围应为                  test, 导致实际依赖范围与预期不符. 这意味着依赖库
                 会在项目的构建、运行和测试阶段均被引入, 从而导致了依赖的冗余. 为了解决这个问题, 开发者最终将                                jenkins-
                 test-harness 的依赖范围修改为预期的     test, 确保它仅在测试阶段被引入.

                                                  <dependency>
                                依赖于         具体配置    <groupId>example</groupId>
                                                     <artifactId>lib</artifactId>
                                                    <version>1.0.0</version>
                          模块 mod       依赖库 lib    </dependency>
                                                              未声明依赖范围, 默认为 compile
                                                     冲突!                          实际范围与预期范围冲突!
                        (a) 类型 1.6    预期范围: test                实际范围: compile
                                依赖于          依赖于
                                       依赖库 lib1   依赖库 lib2: compile
                          模块 mod  依赖于
                                                                               直接依赖与间接依赖范围冲突!
                        (b) 类型 1.7    依赖库 lib2: test  依赖范围冲突!
                                                        <dependency>
                                依赖于         Maven 中具体配置   <groupId>example</groupId>
                                                           <artifactId>lib</artifactId>
                         模块 mod                           <version>1.0.0</version>
                                        依赖库 lib Gradle 中具体配置
                                                        </dependency>
                                  模块同时使用
                                                            依赖版本冲突!        依赖库在 Maven 和 Gradle 中版本冲突!
                        (c) 类型 1.8  Maven 和 Gradle!    implementation “example:lib1: 2.0.0”
                                 通过脚本启动 Gradle      调用启动器 jar
                                                              gradle-wrapper.jar
                          项目 pr           Gradle 启动器脚本 gradlew                     gradle-wrapper.jar 缺失!
                        (d) 类型 2.2
                              通过脚本启动 v5.6.4 版本 Gradle  调用启动器 jar
                                                               gradle-wrapper.jar
                                                                                   gradle-wrapper.jar 异常!
                                          Gradle 启动器脚本 gradlew
                          项目 pr
                                                               校验和错误!
                        (e) 类型 2.3         v5.6.4 版本 jar 的预期校验和: 3dc39a  实际校验和: ad63ba
                                                图 3 出现依赖异味特征的案例

                    这种异味在     Maven  和  Gradle 中都存在, 其产生原因主要在于开发者对依赖库具体使用场景的认知错误, 从而
                 无法选择正确的依赖范围. 虽然          Maven  和  Gradle 中都存在依赖范围的概念, 但由于它们对依赖范围的实现和定义
                 不同, 依赖范围误用在       Maven  和  Gradle  中表现出不同的形式. 由于     Maven  中仅有  6  个固定的依赖范围, 因此
   121   122   123   124   125   126   127   128   129   130   131