(Java)包组织是否有最佳实践?

时间:2010-07-12 06:20:05

标签: java package naming-conventions

不久前,我在这里看到了一个关于java包的细粒度组织的问题。例如,my.project.utilmy.project.factorymy.project.service

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

是否有关于Java程序包组织及其内容的最佳实践?

如何在Java项目中组织课程?

例如,我正在与一些人合作的项目有一个名为beans的包。它最初是一个包含简单豆类的项目,但最终(通过糟糕的经验和缺乏时间)包含所有内容(几乎)。我通过在工厂包中放置一些工厂类(使用创建bean的静态方法的类)来清理它们,但我们有其他类来执行业务逻辑,而其他类则执行简单处理(不使用业务逻辑),如检索来自属性文件的代码消息。

感谢您的想法和意见。

7 个答案:

答案 0 :(得分:147)

我按功能组织包,而不是模式或实现角色。我认为包裹如下:

  • 工厂
  • collections

错了。我更喜欢,例如:

  • 订单
  • 存储
  • 报告

所以我可以通过包可见性隐藏实现细节:订单的工厂应该在订单包中,因此隐藏了有关如何创建订单的详细信息。

答案 1 :(得分:145)

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

  • 关注java package naming conventions
  • 根据功能角色及其业务角色构建包
    • 根据功能或模块细分包。例如com.company.product.modulea
    • 进一步细分可以基于软件中的图层。但是如果你的包中只有几个类,那就不要过分了,那么在包中包含所有内容是有意义的。例如com.company.product.module.webcom.company.product.module.util等。
    • 避免过度使用结构化,IMO避免为例外,工厂等单独包装,除非迫切需要。
  • 如果您的项目很小,请使用少量软件包保持简单。例如com.company.product.modelcom.company.product.util
  • Apache projects上查看一些流行的开源项目。了解他们如何使用结构化,用于各种规模的项目。
  • 在命名时也考虑构建和分发(允许您在不同的包中分发api或SDK,请参阅servlet api)

经过一些实验和试验后,你应该能够想出一个你觉得舒服的结构。不要只关注一个约定,对变化持开放态度。

答案 2 :(得分:35)

简答:每个模块/功能一个包,可能带有子包。将密切相关的东西放在同一个包中。避免包之间的循环依赖。

答案很长:I agree with most of this article

答案 3 :(得分:12)

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

  • 依赖关系。尝试最小化包依赖性,尤其是在功能之间。必要时提取API。
  • 团队组织。在一些组织中,团队在功能上工作,而在其他组中工作。这会影响代码的组织方式,使用它来形式化API或鼓励合作。
  • 部署和版本控制。将所有内容放入模块可以简化部署和版本控制,但更难修复错误。拆分可以实现更好的控制,可扩展性和可用性。
  • 回应变化。组织良好的代码比一个大的泥球更容易改变。
  • 大小(人和代码行)。它需要越大,越正规/标准化。
  • 重要性/质量。有些代码比其他代码更重要。 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移动到support / string,HttpUtil移动到支持/ http等等。

答案 4 :(得分:10)

答案 5 :(得分:4)

我看到有些人推广'逐个功能'而不是'逐层',但多年来我使用了很多方法,发现'逐层'比'逐个功能'更好。< / p>

除此之外,我发现混合:'逐个模块,逐层特征'策略在实践中非常有效,因为它具有“逐个功能”的许多优点:

  • 促进可重用框架的创建(具有两种模型的库) 和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;如果是会计框架,则为“财务”

图层 [model | ui | persistence | security等。]

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

功能例如,财务

subfeatureN 例如,会计

subfeatureN + 1 例如,折旧

*如果moduleType是一个应用程序,但将其放在那里,有时会将'app'排除在外,这使得所有模块类型的包结构都是一致的。

答案 6 :(得分:2)

我不了解包装组织的标准做法。我通常创建包含一些相当广泛的频谱的软件包,但我可以在一个项目中区分。例如,我正在处理的个人项目有一个专门用于我的自定义UI控件的包(充满了子类化swing类的类)。我有一个专门用于我的数据库管理的软件包,我已经为我创建的一组监听器/事件提供了一个软件包,等等。

另一方面,我有一个同事为他所做的几乎所有事情创造了一个新包装。他想要的每个不同的MVC都有自己的包,似乎MVC集是唯一允许在同一个包中的类组。我记得有一次他有5个不同的包,每个包都有一个单独的类。我认为他的方法有点极端(当我们根本无法处理时,团队强迫他减少他的包数),但对于一个非常重要的应用程序,所以将所有内容放在同一个包中。这是你和你的队友必须为自己找到的平衡点。

你可以做的一件事就是试着退后一步思考:如果你是一个介绍给项目的新成员,或者你的项目是作为开源或API发布的,找到你是多么容易/困难想?因为对我而言,这就是我真正想要的包装:组织。与我在计算机上的文件夹中存储文件的方式类似,我希望能够再次找到它们,而无需搜索我的整个驱动器。我希望能够找到我想要的课程,而无需搜索包中所有类的列表。