应用maven groupId命名约定

我正在开发一些项目(目前组织为eclipse项目)。 有一个核心项目,主要提供核心API和一些辅助实现和抽象类。 所有其他项目都依赖于这个项目。

在将项目集成到我们的maven存储库时,我们遇到了maven命名约定的问题。 正如在SO上讨论的那样,groupId通常应该是反向公司域名( com.example )加上项目名称( com.example.foo )。 maven命名约定为子项目(如插件( com.example.foo.plugin ))提供了额外的后缀。

在我们的例子中,我们没有插件,而是核心项目提供的API的多个(大多数是独立的)实现。 我们目前的命名建议是:

  • com.example.foo作为所有项目的groupId,虽然它们被分成不同的java包( com.example.foo包含API, com.example.foo.bar包含bar实现)
  • 项目名称为artifactId,没有引用项目的前缀( bar而不是foo-bar

关键点在于(虽然我们的项目如上所述在包中传播)但它们并不是API核心项目的子项目。

此建议是否符合maven命名约定?

以防万一:这个问题不是要求提出意见,而是要求对上述问题进行辩论。

我想说这是你自己的品味和偏好的问题。

通常,您可以在同一groupId下对类似的模块组进行分组。 例如,您可以拥有以下内容:

 com.foo.bar:parent (parent pom for all projects) com.foo.bar:core-api (some very core classes) com.foo.bar:commons (some common classes) com.foo.bar:io (some IO classes) com.foo.bar:utils (some utility classes) com.foo.bar.messaging:messaging-core (messaging core classes) com.foo.bar.messaging:messaging-rest-api (REST API for messaging) com.foo.bar.messaging:messaging-jms (some JMS code) com.foo.bar.web:rest-api (your restlets) com.foo.bar.web:web-core (core classes to be used by web modules) com.foo.bar.web:web-parent (a parent pom for all your web projects) com.foo.bar.web:web-ui (UI stuff like css/images/js/etc) com.foo.bar.web:web-assembly (a web assembly that bundles all modules) ... (I hope by now you get my drift) ... 

您不一定需要将类以同一groupId下的公共包开头的所有模块分组。 如果你愿意,你可以这样做,但很少人们真正在现实生活中如何使用它。 严格程度和细节程度取决于您,但在工件的情况下,通常无关紧要,因为没有什么可以将包名称绑定到groupId

此外,为模块使用前缀也很有帮助,但由您决定。 如果你愿意,你可以:

 com.foo.bar:bar-parent com.foo.bar:bar-core-api com.foo.bar:bar-commons 

这真的取决于你。 有些人会争辩说,如果你有一个像com.foo.bar这样的groupId ,那么你就不需要在bar-parent有一个bar-前缀。 在某种程度上,这是事实。 但是你可以使用com.foo.bar:parentcom.foo.bar.web:parent ,当你使用像Nexus,Archiva或Artifactory这样的存储库管理器时,你正在寻找parent ,(或者其他一些常见的例如,如“ commons这样的名称,你可能会得到一个相当长的结果列表,而不是bar-parent

最后,重要的是你愿意去的具体细节以及真正适合你需求的细节。 Maven为您提供了所需的所有自由。

所以我看到你有一堆选项遵循maven命名约定……

Foo指的是核心API,bar指的是实现。

  1. com.example.foo(指核心api)作为组,然后实现为foo-bar(约定表示你在工件名称中包含一个挂钩回到组)。

  2. com.example.bar作为thr组,工件id是bar-impl或其他一些适当的后缀

  3. com.example.foo.bar作为group和bar-impl或其他一些适当的后缀。

对于1,您对陌生人说:实现与API紧密耦合,并且具有密切相关的发布周期。 当发布核心API的新版本时,还会发布一个版本的实现。 此外,实现是核心API的子项,并不是真正独立。 你也说bar的核心业务是实现bar并且没有什么价值(除此之外没什么用)。

2中,您说核心API的实现确实具有自己的生命周期,并且通常不会在与API相同的周期中发布。 此外,它不是核心API的子项目,因此可以独立存在。 换句话说,它的核心业务和用途不仅仅是作为foo的实现。 如果酒吧可以有兄弟姐妹,这是特别有吸引力的。

3是两者之间的中间道路。 它表示bar本身具有价值,并且作为foo的实现具有重要意义,并且还可能允许兄弟姐妹。 它稍微改进了2,因为它提供了一些反馈,这个工件是foo的实现。 再说一次,如果酒吧可以有兄弟姐妹这更有意义。

所以我想你需要选择你的API实现位置。 最大的驱动力可能是酒吧是否可以有兄弟姐妹。

事物的命名非常重要,名称应该立即传达重要信息。 出于这个原因,我公司使用的约定规定组ID对于特定事物的所有实现应该是相同的:每个组的ID都是com.example.foo,因为它们都是它的实现。 项目名称应该引用接口,并用其特定实现的名称连字,主要父pom标记为’parent’:

 com.example.foo:parent com.example.foo:foo-bar com.example.foo:foo-bat com.example.foo:foo-baz 

这样,您可以从名称中一眼看出这些事物的确切关系,并且工件名称也分别表示它们是不同类型的foo。 这也意味着java代码中的导入遵循完全相同的结构。 它还使java中的导入非常易读且易于理解。

我说可以将所有工件放在同一个groupId中。 但是你应该在适当的地方使用子项目模式。

例如,Spring在一个groupId, org.springframework中包含了所有主要工件。 这包括spring的核心以及JMS,ORM和WMV子项目。 但是像Spring Boot这样更大的子项目有一个单独的groupId, org.springframework.boot 。 我想说这是一个很好的模式。

我只想添加关于父POM的命名约定的注释。 一些回复,包括carlspring的回答和Steve K的答案 ,表明父母pom只是命名为parent

 com.example.foo:parent com.example.foo:foo com.example.foo:foo-bar com.example.foo:foo-bat com.example.foo:foo-baz 

我完全同意这种观点,因为父POM不是一个子模块,这就是foo-parent似乎暗示的内容。

选项1: com.example.foo:parentcom.example.foo:parent

然而,使用简单的parent作为工件ID存在一个很大的问题,除了在Maven存储库中搜索它时它没有提供太多信息这一事实。 如果将项目导入Eclipse,IDE将使用parent作为项目名称! 这是不雅观的,尝试导入两个使用此约定的项目将导致痛苦。

但我也不想将工件命名为foo-parent ,因为我提到它不是子模块。 此外,它可能会在子模块的中间进行排序,因此很难在我的IDE中找到它。

选项2: com.example.foo:foo-.parentcom.example.foo:foo-.parent

经过深思熟虑和实验,我决定为父POM工件ID提出一个约定: project-.parent 。 (是的,Maven允许这个标识符。)这表明工件是“项目”的一部分,但是以a开头. 它表明它是一个特殊的POM,有点像元数据文件或配置目录。 另外,它将它排序到模块的前面(尽管不在单个project工件ID的前面)。 所以模块坐标看起来像这样:

 com.example.foo:foo com.example.foo:foo-.parent com.example.foo:foo-bar com.example.foo:foo-bat com.example.foo:foo-baz 

但是有一个缺点:许多工具似乎不支持。 例如,在工件ID中有点会导致JitPack , JFrog Artifactory和OSGi Bnd出现问题。

选项3: com.example.foo:foo--parentcom.example.foo:foo--parent

然后我考虑使用foo--parent ,甚至只是foo-- 。 但是,因为-在工件ID中用作语义上的组件分隔符,我担心如果两个破折号彼此相邻,工具可能会打嗝。 再添加一个版本到工件的末尾(例如foo---1.0.0.jar )看起来有点奇怪。

选项4: com.example.foo:foo_com.example.foo:foo_

然后我偶然发现了一篇博客文章 ,指出Eclipse有一个分层次查看项目的选项! 我突然意识到我的主要问题是一个特定的用例:聚合POM与父POM相同,主项目工件在子目录中。 例如,在foo库中,项目位于foo/foo ,那么我该如何命名聚合POM工件ID?

突然排序不再那么重要了,因为Eclipse会在树中显示根项目。

  • 对于独立的父项目,我可以屈服于约定并使用foo-parent
  • 对于主工件位于根目录的项目,没有问题,因为根工件ID将简单地命名为foo

所以剩下的问题是这样的项目:

 …/foo/pom.xml #com.example.foo:??? …/foo/foo/pom.xml #com.example.foo:foo …/foo/foo-bar/pom.xml #com.example.foo:foo-bar …/foo/foo-bat/pom.xml #com.example.foo:foo-bat …/foo/foo-baz/pom.xml #com.example.foo:foo-baz 

我想给它一个foo的工件ID,但我不能这样做,因为主要的foo工件在一个子目录中。 所以对于这个特例,我倾向于foo_

 …/foo/pom.xml #com.example.foo:foo_ …/foo/foo/pom.xml #com.example.foo:foo …/foo/foo-bar/pom.xml #com.example.foo:foo-bar …/foo/foo-bat/pom.xml #com.example.foo:foo-bat …/foo/foo-baz/pom.xml #com.example.foo:foo-baz 

这在Eclipse的树的根部显示为foo_ ,并且工具没有太多机会出现尾随下划线的问题(至少比点或重复的破折号少)。

我有兴趣获得有关此讨论和我(当前)结论的反馈。