不久前,我看到这里回答了一个关于Java包的细粒度组织的问题。例如,my.project。my.project跑龙套。工厂,my.project。服务等。

在Java中有关于包组织的最佳实践吗?它们包含什么?

如何在Java项目中组织类?

For instance, a project I'm working on with a few people has a package called beans. It started out being a project containing simple beans, but it has ended up (through poor experience and lack of time) containing everything (almost). I've cleaned them up a little, by putting some factory classes in a factory package (classes with static methods that create beans), but we have other classes that do business logic and others that do simple processing (not with business logic) like retrieving a message for a code from a properties file.


我不知道包装组织的标准做法。我通常创建的包涵盖一些相当广泛的范围,但我可以在一个项目中进行区分。例如,我目前正在从事的个人项目有一个专门用于定制UI控件的包(充满了派生swing类的类)。我有一个专门用于数据库管理的包,我有一个用于我创建的一组侦听器/事件的包,等等。

On the other hand I've had a coworker create a new package for almost everything he did. Each different MVC he wanted got its own package, and it seemed a MVC set was the only grouping of classes allowed to be in the same package. I recall at one point he had 5 different packages that each had a single class in them. I think his method is a little bit on the extreme (and the team forced him to reduce his package count when we simply couldn't handle it), but for a nontrivial application, so would putting everything in the same package. It's a balance point you and your teammates have to find for yourself.

One thing you can do is try to step back and think: if you were a new member introduced to the project, or your project was released as open source or an API, how easy/difficult would it be to find what you want? Because for me, that's what I really want out of packages: organization. Similar to how I store files in folder on my computer, I expect to be able to find them again without having to search my entire drive. I expect to be able to find the class I want without having to search the list of all classes in the package.


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

Follow Java package naming conventions Structure your packages according to their functional role as well as their business role Break down your packages according to their functionality or modules. e.g. com.company.product.modulea Further break down could be based on layers in your software. But don't go overboard if you have only few classes in the package, then it makes sense to have everything in the package. e.g. com.company.product.module.web or com.company.product.module.util etc. Avoid going overboard with structuring, IMO avoid separate packaging for exceptions, factories, etc. unless there's a pressing need. If your project is small, keep it simple with few packages. e.g. com.company.product.model and com.company.product.util, etc. Take a look at some of the popular open source projects out there on Apache projects. See how they use structuring, for various sized projects. Also consider build and distribution when naming (allowing you to distribute your API or SDK in a different package, see the servlet API)

经过一些实验和试验,你应该能够提出一个你感到舒服的结构。不要拘泥于一种惯例,要乐于接受改变。


我按特性组织包,而不是按模式或实现角色。我认为套餐包括:

豆子 工厂 集合

是错误的。

我更喜欢,例如:

订单 商店 报告

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


在Java中有关于包组织的最佳实践吗?它们包含什么?

没有,没有。有很多想法,很多观点,但真正的“最佳实践”是运用你的常识!

(请阅读没有最佳实践来了解“最佳实践”和推广它们的人。)

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

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

我还应该补充一点,有一个被广泛接受的包名称最佳实践。也就是说,您的包名称应该以您的组织域名的倒序开始。如果你遵循这条规则,你就可以降低你的(完整的)类名与其他人的类名冲突所引起的问题的可能性。


我见过一些人提倡“按功能打包”而不是“按层打包”,但多年来我使用了不少方法,发现“按层打包”比“按功能打包”要好得多。

此外,我还发现了一种混合策略:“按模块打包,层然后功能”策略在实践中效果非常好,因为它具有“按功能打包”的许多优点:

促进可重用框架(具有两种模型的库)的创建 和用户界面方面) 允许即插即用层实现——“按特性包”几乎不可能实现,因为它将层实现放在与模型代码相同的包/目录中。 更多的……

我在这里深入解释:Java包的名称结构和组织,但我的标准包结构是:

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

地点:

revdomain反向域名,如com.mycompany moduleType(应用程序框架* | | util) 例如,如果模块类型是app,则返回myAppName;如果模块类型是会计框架,则返回'finance' 层[模型|ui|持久化|安全等,] layerImpl,例如,wicket, jsp, jpa, jdo, hibernate(注意:如果layer是model则不使用) 特征,如金融 例如,会计 subfeatureN+1,例如,折旧

如果moduleType是一个应用程序,有时'app'会被省略,但是把它放在那里可以使所有模块类型的包结构保持一致。


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

长话短说:我同意本文的大部分观点


我更喜欢特性优先于层,但我想这取决于你的项目。考虑你的力量:

Dependencies Try minimize package dependencies, especially between features. Extract APIs if necessary. Team organization In some organizations teams work on features and in others on layers. This influence how code is organized, use it to formalize APIs or encourage cooperation. Deployment and versioning Putting everything into a module make deployment and versioning simpler, but bug fixing harder. Splitting things enable better control, scalability and availability. Respond to change Well organized code is much simpler to change than a big ball of mud. Size (people and lines of code) The bigger the more formalized/standardized it needs to be. Importance/quality Some code is more important than other. APIs should be more stable then the implementation. Therefore it needs to be clearly separated. Level of abstraction and entry point It should be possible for an outsider to know what the code is about, and where to start reading from looking at the package tree.

例子:

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 feature
    + io
    + config
    + persistence
    + web

这只是一个例子。这是相当正式的。例如,它为feature1定义了两个接口。通常这不是必需的,但如果不同的人使用不同的方法,这可能是一个好主意。你可以让内部API扩展public。

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