(Java)软件包组织有最佳实践吗?

前一段时间,我在这里看到一个关于Java包的细粒度组织的问题。 例如,my.project.util,my.project.factory,my.project.service等

我现在找不到,所以我不妨问这个问题。

关于Java中包的组织方面是否有最佳实践?

你如何组织你的Java项目中的类?

例如,我正在和几个人一起工作的项目有一个名为beans的包。 它开始是一个包含简单的豆类的项目,但最终(通过糟糕的经验和缺乏时间)包含了一切(几乎)。 我已经通过将一些工厂类放入工厂包(具有创buildbean的静态方法的类)来清理它们,但是我们有其他类来执行业务逻辑,而其他类做简单处理(而不是业务逻辑),比如检索来自属性文件的代码消息。

你的想法和意见,表示赞赏。

包装组织或包装结构通常是一个热烈的讨论。 以下是一些简单的包命名和结构指南:

  • 遵循java 包的命名约定
  • 根据他们的职能angular色以及他们的业务angular色来组织您的软件包
    • 根据其function或模块分解您的软件包。 例如com.company.product.modulea
    • 进一步的细分可以基于软件中的图层。 但是如果你的软件包中只有几个类,就不要太过分了,那么在软件包中包含所有东西都是有意义的。 如com.company.product.module.webcom.company.product.module.util
    • 避免过度结构化,IMO避免为例外,工厂等单独包装,除非有迫切的需求。
  • 如果你的项目很小,只需要很less的软件包就可以保持简单。 如com.company.product.modelcom.company.product.util
  • 看一看Apache项目中的一些stream行的开源项目 。 看看他们如何使用结构化,为各种规模的项目。
  • 在命名时还要考虑构build和分发(允许您在不同的包中分发api或SDK,请参阅servlet api)

经过几次实验和试验之后,你应该能够想出一个你感觉舒适的结构。 不要拘泥于一个惯例,要随时改变。

我按function组织软件包,而不是模式或实现angular色。 我觉得包像:

  • 工厂
  • 集合

错了。 我比较喜欢,例如:

  • 命令
  • 商店
  • 报告

所以我可以通过包可见性隐藏实现细节:订单的工厂应该在订单包中,所以关于如何创build订单的细节是隐藏的。

简短的回答:每个模块/function一个包,可能有子包。 把密切相关的东西放在一起。 避免包之间的循环依赖。

长答案: 我同意这篇文章的大部分内容

我更喜欢图层之前的function,但我想这取决于你的项目。 考虑你的力量:

  • 依赖。 尽量减less软件包依赖性,特别是在function之间。 如有必要,提取API。
  • 团队组织。 在一些组织中,团队在function上工作,在其他层面上工作。 这影响了代码是如何组织的,用它来forms化API或者鼓励合作。
  • 部署和版本控制。 把所有内容放到一个模块中,使得部署和版本化变得更简单,但是bug修复更困难。 拆分事物可以实现更好的控制,可扩展性和可用性。
  • 回应变化。 组织良好的代码要比大泥土变得简单得多。
  • 大小(人和行的代码)。 它越需要正规化/标准化。
  • 重要性/质量。 有些代码比其他代码更重要。 API应该比实现更稳定。 所以需要明确分开。
  • 抽象级别和入口点。 外人应该有可能知道代码是关于什么的,以及从看包树开始阅读的地方。

例:

 com/company/module + feature1/ - MainClass // The entry point for exploring + api/ // Public interface, used by other features + domain/ - AggregateRoot + api/ // Internal API, complements the public, used by web + impl/ + persistence/ + web/ // presentation layer + services/ // Rest or other remote API + support/ + feature2/ + support/ // Any support or utils used by more than on feaure + io + config + persistence + web 

这只是一个例子。 这是相当正式的。 例如,它为feature1定义了2个接口。 通常这不是必需的,但是如果不同的人使用不同的话,这可能是个好主意。 你可以让内部api扩大公众。

我不喜欢“impl”或“support”这个名字,但是它们帮助把不重要的东西从重要的(域和API)中分离出来。 说到命名,我喜欢尽可能具体。 如果你有一个名为'utils'的包有20个类的包,请将StringUtils移动到支持/string,HttpUtil支持/ http等等。

关于Java中包的组织方面是否有最佳实践?

不是真的没有。 有很多想法和很多意见,但“最佳实践”是使用你的常识!

但是,有一个可能被广泛接受的原则。 你的包结构应该反映你的应用程序的(非正式的)模块结构,你应该尽量减less(或理想上完全避免)模块之间的任何循环依赖。

(一个包/模块中的类之间的循环依赖关系是很好的,但是包间循环往往会使得它很难理解你的应用程序的体系结构,并且可能成为代码重用的障碍,特别是如果你使用Maven,你会发现循环组件间/组件间依赖意味着整个相互联系的混乱必须是一个Maven神器。)

我还应该补充说,有一个被广泛接受的最佳包装名称的做法。 那就是你的软件包名称应该以相反的顺序从你的组织的域名开始。 如果你遵循这个规则,你可以减less你的(全class)名字与其他人的冲突造成问题的可能性。

我曾经看到一些人一个一个的“逐个包装”地推广“包装”,但是我已经用了很多年的方法,发现“一层一层”比“一个包装”要好得多。

除此之外,我发现一个混合模式:“模块化,层次化,特征化”策略在实践中效果非常好,因为它具有“按function打包”的许多优点:

  • 促进创build可重用的框架(包含模型和UI方面的库)
  • 允许即插即用图层实现 – “按特征包装”几乎是不可能的,因为它将图层实现放置在与模型代码相同的包/目录中。
  • 还有很多…

我在这里深入解释: Java Package Name Structure and Organization,但是我的标准包结构是:

revdomain.moduleType.moduleName.layer。[layerImpl] .feature.subfeatureN.subfeatureN + 1 …

哪里:

revdomain反向域例如com.mycompany

moduleType [app * | framework | util]

moduleName例如myAppName,如果模块types是一个应用程序,或者是财务,如果它是一个会计框架

[model | ui | persistence | security等,]

layerImpl例如:wicket,jsp,jpa,jdo,hibernate(注:如果图层是模型,则不使用)

function,如财务

子特征,例如会计

子特征N + 1例如折旧

*如果moduleType是一个应用程序,但是将其放在那里,有时会忽略“app”,这使得所有模块types的包结构都是一致的。

我不知道包组织的标准做法。 我通常会创build一些覆盖范围相当广泛的软件包,但我可以在一个项目中进行区分。 例如,我目前正在从事的一个个人项目有一个专门用于我的自定义UI控件(包含swing子类的子类)的包。 我有一个专门用于我的数据库pipe理的软件包,我已经为我创build的一组监听器/事件提供了一个软件包,依此类推。

另一方面,我有一个同事为他做的几乎所有事情都创build了一个新的包。 他想要的每个不同的MVC都有自己的包,而且似乎MVC集合是允许在同一个包中的唯一类的组合。 我记得有一次他有5个不同的包,每个包都有一个class级。 我认为他的方法有些偏激(当我们无法处理这个问题时,团队迫使他减less包装数量),但是对于一个不重要的应用来说,把所有东西都放在同一个包里。 这是一个平衡点,你和你的队友必须自己find。

你可以做的一件事就是回想一下:如果你是一个新成员,或者你的项目是以开源或者API的forms发布的话,那么find你想要的东西多么容易/困难呢? 因为对我来说,这就是我真正想要的软件包:组织。 类似于我的电脑上的文件夹存储文件,我希望能够find他们,而无需search我的整个驱动器。 我尊重能够find我想要的类,而不必search包中的所有类的列表。

我通常按​​层次组织,因为我写了很多networking应用程序。 所以我会有持久性,服务,模型,视图,实用程序等