【问题标题】:Java package structure conventionJava包结构约定
【发布时间】:2018-10-24 01:32:47
【问题描述】:

我正在使用 Typescript 和 Javascript,我停下来思考了一下命名空间以及我们如何在 Java 中组织代码。

现在,我经常看到多个具有相同目的的类,只是用于不同的数据,被放置在不同名称的不同包中。

虽然将这些类放在不同的包中是保持项目/模块处于良好状态的好习惯,但为什么我们必须给它们不同的名称?我的意思是,它们的目的是一样的。

我可以自己回答这个问题:因为我们经常在同一个单元中使用这些类,它们会发生冲突,因此需要一个很长的完整包规范。

但是我们不是违反了 DRY 原则吗?我们应该使用我们的目录(包)结构来了解这些类在哪个域空间中工作。

正如我在上面所写的,我想许多开发人员并没有遵守这个 DRY 原则,只是为了避免长包名。那么,我们为什么要创建那些 monstruos 包层次结构呢?
谷歌搜索"Java packages best practices" 会得到如下建议:

com.mycompany.myproduct.[...]

这些建议来自哪里?我们不是在浪费空间吗?
我们显然不想每次都这么写。

MyClass myInstance;
com.mycompany.myproduct.mypackage.MyClass myOtherInstance;

但它本来可以

myfeature.MyClass myInstance
myotherfeature.MyClass myInstance;

我们甚至可以为两者指定完整的包。
那么,这些最佳实践从何而来?

如前所述,这个约定可以追溯到 Java 的第一个版本。 名称冲突可以通过使用它们的 short 包的层次结构限定导入的依赖项(例如类路径库)类来轻松解决,强调并保持 我们的自己的代码更清晰。同样重要的是要记住我们可以访问包级别的可见性,这在当今似乎被忽视了。

【问题讨论】:

  • 约定的“反向域”名称部分是为了使其全球唯一,因此您不会与库等发生名称冲突。如果您认为仅使用 myfeature 会即使在一家公司内也足够独特,那么我认为您只为(非常)小公司工作过;)
  • @MarkRotteveel 谢谢马克。虽然我明白你在说什么,但我觉得这很废话。这不只是一个既定的坏习惯吗?
  • 对于小公司,实际上恰恰相反,是的,我经常看到这种包结构滥用。如果我们谈论的是模块,那么一个模块应该代表一个单一的特性,所以没有名称冲突。部分问题来自于我们没有认真思考我们正在做什么以及我们正在从事的领域
  • 代码可能是单一应用程序的一部分,这会导致任何特定开发人员不知道应用程序中其他地方已经存在类似代码,或者开发人员知道类似代码但决定(无论原因)不创建旨在跨功能/域使用的包并重构代码。副作用是 com.mycompany.business.area.feature1.util 和 com.mycompany.business.area.feature2.util 等包中的代码几乎重复。
  • 记住包可见性是有原因的也很重要。可惜开发者忘记了它是可用的。

标签: java


【解决方案1】:

正如评论者指出的那样,这个约定是在 Java 的一开始就建立起来的,允许一个全局命名空间用于所有类。

影响这一点的 Java 有一点——它与 TypeScript 和 JavaScript 不同——类的名称及其包(以及它使用的所有类和包的名称)固定在编译时。您不能在不修改其源代码的情况下将类重新组合到不同的层次结构中。所以它不像解释语言那样灵活,您可以移动层次结构并更改加载代码的位置。

例如,您当然可以将应用程序中的所有内容都放在顶级包中,并且非常有信心您会侥幸成功。只要每个人else都遵循现有的约定,您就可以做到这一点。一旦他们停止这样做,并且库开始将类放在他们想要的任何地方,您就会遇到冲突,您将不得不更改您的应用程序。或者库会开始相互冲突,如果你没有源,你将无法真正修复它。

所以有充分的理由。

我基于意见的部分——坚持约定和语言(或平台)的文化是有道理的。在我们看来,即使这些约定很愚蠢。有一个地方可以打破它们,但优势必须非常大。其他开发人员将习惯于约定,工具会对约定做出假设……通常顺其自然是有意义的。

对 Java 中的每个属性都使用 getter 和 setter 真的有意义吗?如果您了解您正在使用的域,那么它很可能不会。但是停止这样做,你的代码对你团队的其他成员没有意义,你必须在人们加入时不断地重新审视这个决定,等等。

如果这是一个单人项目,并且永远都是,当然,你可以做你想做的事。

【讨论】:

  • 我并不是说我们不应该遵守约定,我只是说 99% 的情况下它没有意义。即使库发生冲突,也只需使用 SHORT 限定的包名,并且更喜欢强调您的代码。正如我在我的问题中所写的那样,使用较短的层次结构,指定限定名称会更容易,甚至更漂亮。正如您所写,这个大会是在 20 年前诞生的,可能是时候多考虑一下我们的工作了。
猜你喜欢
  • 1970-01-01
  • 2012-05-22
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-11
相关资源
最近更新 更多