对maven依赖的一些看法



目前我们的项目大多使用Maven进行包依赖管理, 而像pom里依赖该怎么写, 我总认为这是不值得单独拿出来说, 因为这是基本功, 就像是程序员的基本素养, 大家都很熟悉, 实在没啥可说的了. 然而做过如此多的项目之后, 我发现这里却有着非常严重的问题, 写法真是千奇百怪, 简直辣眼睛, 我实在看不下去了, 就把我看到的一些现象晒出来看看, 另附上我的一些看法.

同一个包依赖声明两次

现象描述

同一个groupId同一个artifactId同一个version的包在同一个pom文件里被硬生生的声明了两次!

个人看法

虽然这不会引起什么大的问题, 但显然是开发者的态度问题, 估计内容都是copy过来的, 连看都不看, copy完就不管了

完全没有用到的包依赖

现象描述

这个没用到不是传递依赖进来的, 而是直接在pom里声明了, 但是没有使用.

个人看法

产生的原因, 有可能有以下几点:

  1. 传递依赖中版本不一致, 为了统一版本而声明; 这种产生原因是可以接受的, 但我认为也是可以避免的(比如所有的包都采用变量声明来进行版本管理, 就不会出现这样的局面).
  2. 原来使用过该包提供的功能, 后来相关代码删掉了, 忘了修改pom里的包依赖; 这种情况就尽量避免吧
  3. 不知道这个包有什么用或不知道是否能用到, 加进来再说; 呵呵, 这种情况还真有!

没有使用dependencyManagement进行包管理

现象描述

完全没用dependencyManagement的情况很少, 大部分情况都是个别的包直接在dependencies中声明了依赖

个人看法

虽然看似省事儿, 但不便于管理

版本管理直接声明而不是采用变量形式

现象描述

<!-- 直接声明版本 -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

个人看法

推荐使用变量控制版本, 强烈推荐参考Sprint Boot提供的各种starter

<!-- 版本通过变量统一管理 -->
<guava.version>20.0</guava.version>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>${guava.version}</version>
</dependency>

不过这样有可能引发一个问题, 用于版本管理的变量名可能不一样. 变量名尽量向Spring Boot看齐, 后面还会说到.

直接在dependencyManagement进行execution

现象描述

需要排除掉某些包的时候, 直接在dependencyManagement中进行execution.

个人看法

这种情况是真是存在的, 并且我认为这是非常严重的 错误.
通常项目中有可能包含多个子模块, 我们可以统一在父pom中进行包版本管理, 在各个子模块中直接依赖某包.
假设在子模块1中因为某包的传递依赖包存在冲突而在父pomdependencyManagement中直接把冲突的包进行execution, 那么在子模块2中使用这个包时, 就是不完整的.

提供的API依赖过于庞大

现象描述

现实中总会遇到需要与其他系统交互的场景, 比如进行RPC通信. 通常情况下我们需要引入其他系统提供的API, 而不关注对方具体怎么实现.
但是所依赖的的这个第三方APIpom依赖过于庞大, 有图为证: 垃圾的API

上面那一坨东西全都是所依赖的API传递依赖进来的

个人看法

我只想说, API提供方估计是跟使用方有什么深仇大恨. 如果API里依赖了一两个其他包勉强还能接受, 但是依赖这么多, 实在是让使用方太痛苦了.
maven提供了一个可选依赖的属性optional, 值为true时表示该依赖是可选的, 不强制引入, 如果使用方要用到某包功能时, 需要自行引入.

版本管理的变量名不一致问题

现象描述

继承某父pom是很常见的, 在dependencyManagementimport其他pom文件做版本统一管理也是一个避免依赖冲突的常用方法. 但当两个文件同时采用变量控制版本, 而变量名字不一样时, 就会出现问题. 比如, 父pom中有<com.google.guava.version>18.0</com.google.guava.version>, 而import进来的pom文件有<guava.version>20.0</guava.version>, 这个时候起作用的是哪个?

个人看法

对于版本控制变量的名字, 希望都向Spring Boot看齐, 如果真出现了上面的情况, 优先级是:父pom > import, 也就是上面的情况实用的guava版本为18.0. 若想改成20.0, 需要使用父pom中的变量重新声明下其值;
即使父pom中为<guava.version>18.0</guava.version>, 变量名一样, 版本不一样时, 仍是父pom起作用.