应用maven groupId命名约定

时间:2014-09-01 17:22:48

标签: java maven

我正在开发一些项目(目前组织为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命名约定?

以防万一:此问题要求提出意见回复,但要求对上述问题进行辩论。

5 个答案:

答案 0 :(得分:11)

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

通常,您可以在同一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

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

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

答案 1 :(得分:3)

所以我看到你有很多选项遵循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 and bar-impl或其他一些适当的后缀。

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

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

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

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

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

我只想添加有关父POM命名约定的注释。包括answer by carlspringanswer by by 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:parent

但是,仅使用parent作为工件ID除了在Maven存储库中搜索时不会提供太多信息的事实外,还有一个大问题。如果将项目导入Eclipse,IDE将使用parent作为项目名称!这是不雅观的,尝试导入两个使用此约定的项目会造成麻烦。

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

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

经过大量的思考和实验,我决定为父POM工件ID提出一个约定:project-.parent。 (是的,Maven允许使用此标识符。)这表明工件是“项目”的一部分,但是通过以.开头,表明它是一个特殊的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中看起来像圆点会导致JitPackJFrog ArtifactoryOSGi Bnd出现问题。

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

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

选项4:com.example.foo:foo_

然后我偶然发现了blog entry,指出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

我想给它一个工件ID foo,但是我不能这样做,因为主要的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_,并且在工具上出现下划线的可能性不大(至少比点或重复的破折号少)

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