您在Java项目中使用什么策略来命名包?为什么?[闭门]

关闭。这个问题是基于意见的。它目前不接受答案。

<hr class=“my12大纲无baw0 bb bc-POWER-400”/

想改进这个问题吗?编辑这篇文章,更新这个问题,以便用事实和引文来回答。

四年前关闭

改进这个问题

我在一段时间前就想到了这一点,最近当我的商店正在开发第一款真正的Java web应用程序时,它又重新出现了

作为一个介绍,我看到了两种主要的包命名策略。(要清楚,我不是指整个“domain.company.project”部分,我是指下面的包约定。)总之,我看到的包命名约定如下:

  1. 功能性:根据其体系结构功能命名包,而不是根据业务域命名包。这方面的另一个术语可能是根据“层”命名。因此,您将有一个*.ui包、一个*.domain包和一个*.orm包。您的包是水平切片,而不是垂直切片皮质醇的

    这比逻辑命名更常见。事实上,我不相信我曾经见过或听说过这样的项目。这当然让我产生了怀疑(有点像认为你已经找到了NP问题的解决方案)因为我不是非常聪明,我认为每个人都有很好的理由这样做。另一方面,我并不反对人们错过房间里的大象,而且我从来没有听到过关于以这种方式命名包的实际争论。这似乎是事实上的标准

  2. 逻辑:根据包的业务域标识对包进行命名,并将与该功能垂直部分相关的每个类放入该包中

    正如我之前提到的,我从未见过或听说过这一点,但这对我来说意义重大

    1. 我倾向于垂直而不是水平地接近系统。我想进入并开发订单处理系统,而不是数据访问层。显然,在开发该系统的过程中,我很有可能会接触到数据访问层,但问题是我不这么认为。这当然意味着当我收到变更单或想要实现一些新功能时,最好不要为了找到所有相关的类而在一堆包中四处搜索。相反,我只查看X包,因为我所做的与X有关

    2. 从开发的角度来看,我认为让您的软件包记录您的业务领域而不是体系结构是一个重大的胜利。我觉得体系结构几乎总是系统的一部分,更难探索,因为系统的体系结构,特别是在这一点上,在其实现中几乎变得平淡无奇我可以使用这种命名约定来到一个系统,从软件包的命名中立即知道它处理订单、客户、企业、产品等,这似乎非常方便

    3. 这似乎可以让您更好地利用Java的访问修饰符。这可以让您更清晰地将接口定义到子系统中,而不是系统的层中。因此,如果您有一个希望透明持久化的orders子系统,从理论上讲,您可以不让任何其他人知道首先,它是持久性的,不必为dao层中的持久性类创建公共接口,而是用它处理的类来包装dao类。显然,如果你想公开这个功能,你可以为它提供一个接口或将其公开。这看起来就像你通过将系统功能的垂直部分分割到多个包中

    4. 我想我能看到的一个缺点是,它确实使剥离层变得有点困难。不只是删除或重命名一个包,然后用另一种技术删除一个新的包,你必须进入并更改所有包中的所有类。但是,我不认为这有什么大不了的。我这可能是因为缺乏经验,但我不得不想象,与您在系统中输入和编辑垂直特征切片的次数相比,您交换技术的次数相形见绌

因此,我想接下来的问题是你,你如何命名你的包裹以及为什么?请理解,我不一定认为我在这里偶然发现了金鹅之类的东西。我对这一切都很陌生,大部分是学术经验。但是,我无法发现我推理中的漏洞,所以我希望你们都能这样做,以便我能够继续前进

对于包设计,我首先按层划分,然后按其他一些功能划分

还有一些附加规则:

  1. 从最一般(底部)到最具体(顶部)堆叠层
  2. 每一层都有一个公共接口(抽象)
  3. 一个层只能依赖于另一层的公共接口(封装)
  4. 层只能依赖于更一般的层(从上到下的依赖关系)
  5. 层优选地取决于其正下方的层

因此,例如,对于web应用程序,应用程序层中可以有以下层(从上到下):

  • 表示层:生成将在客户端层中显示的UI
  • 应用层:包含特定于应用程序的逻辑,有状态
  • 服务层:按域分组功能,无状态
  • 集成层:提供对后端层(db、jms、电子邮件等)的访问

对于生成的包布局,以下是一些附加规则:

  • 每个包名称的根是&lt;prefix.company&gt;&lt;appname&gt;&lt;layer&gt;
  • 层的接口按功能进一步划分:&lt;root&gt;&lt;logic&gt;
  • 层的私有实现前缀为private:&lt;root&gt;。private

下面是一个布局示例

表示层按视图技术划分,也可以按(组)应用程序划分

com.company.appname.presentation.internal
com.company.appname.presentation.springmvc.product
com.company.appname.presentation.servlet
...

应用层被划分为用例

com.company.appname.application.lookupproduct
com.company.appname.application.internal.lookupproduct
com.company.appname.application.editclient
com.company.appname.application.internal.editclient
...

服务层被划分为业务域,受后端层中的域逻辑的影响

com.company.appname.service.clientservice
com.company.appname.service.internal.jmsclientservice
com.company.appname.service.internal.xmlclientservice
com.company.appname.service.productservice
...

集成层分为“技术”和访问对象

com.company.appname.integration.jmsgateway
com.company.appname.integration.internal.mqjmsgateway
com.company.appname.integration.productdao
com.company.appname.integration.internal.dbproductdao
com.company.appname.integration.internal.mockproductdao
...

像这样分离包的优点是更容易管理复杂性,并且增加了可测试性和可重用性。虽然这看起来是一个很大的开销,但根据我的经验,它实际上是非常自然的,每个在这种结构(或类似结构)上工作的人都会在几天内学会它

为什么我认为纵向方法不太好

在分层模型中,多个不同的高级模块可以使用同一个低级模块。例如:您可以为同一应用程序构建多个视图,多个应用程序可以使用同一服务,多个服务可以使用同一网关。这里的诀窍是,在层间移动时,功能级别会发生变化。更具体层中的模块不会在更一般层中的模块上映射1-1,因为它们所表示的功能级别不会映射1-1

当您使用垂直方法进行包设计时,即首先按功能划分,然后将具有不同功能级别的所有构建块强制放入同一个“功能套”。您可以设计通用模块

发表评论