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

2024-05-18

我不久前就想过这个问题,最近当我的商店正在开发第一个真正的 Java Web 应用程序时,这个问题又重新出现了。

作为介绍,我看到两个主要的包命名策略。 (需要明确的是,我并不是指其中的整个“domain.company.project”部分,而是指其下面的包约定。)无论如何,我看到的包命名约定如下:

  1. 功能性:根据包的架构功能而不是根据业务领域的身份来命名包。另一个术语可能是根据“层”命名。因此,您将有一个 *.ui 包、一个 *.domain 包和一个 *.orm 包。您的包是水平切片而不是垂直切片。

    This is much比逻辑命名更常见。事实上,我认为我从未见过或听说过这样做的项目。这当然让我感到怀疑(有点像认为你已经想出了一个 NP 问题的解决方案),因为我不是很聪明,而且我认为每个人都必须有充分的理由这样做。另一方面,我并不反对人们只是错过了房间里的大象and我从未听过真正的争论for以这种方式进行包命名。这似乎只是事实上的标准。

  2. 逻辑:根据业务域身份命名您的包并将与垂直功能部分相关的每个类放入该包中。

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

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

    2. 从开发的角度来看,我认为让你的包记录你的业务领域而不是你的架构是一个重大胜利。我觉得域几乎总是系统中更难理解的部分,因为系统的架构,特别是在这一点上,在其实现中几乎变得平凡。事实上,我可以进入具有这种命名约定的系统,并立即从包的命名中知道它处理订单、客户、企业、产品等,这似乎非常方便。

    3. 看起来这可以让您更好地利用 Java 的访问修饰符。这使您可以更清晰地定义子系统的接口,而不是系统各层的接口。因此,如果您有一个希望透明持久的订单子系统,理论上您可以永远不要让其他任何东西知道它是持久的,因为不必在 dao 层中创建其持久性类的公共接口,而是将 dao 类打包在仅涉及它所处理的类。明显地,if如果您想公开此功能,您可以为其提供接口或将其公开。通过将系统功能的垂直部分拆分到多个包中,您似乎会损失很多。

    4. 我想我能看到的一个缺点是它确实使剥离图层变得更加困难。您必须进入并更改所有包中的所有类,而不是仅仅删除或重命名包,然后使用替代技术放置一个新包。不过,我不认为这有什么大不了的。这可能是由于缺乏经验,但我必须想象,与您进入并编辑系统中的垂直功能切片的次数相比,您更换技术的次数相形见绌。

所以我想你会遇到这样的问题:你如何命名你的包以及为什么?请理解,我不一定认为我在这里偶然发现了金鹅之类的东西。我对这一切都很陌生,主要是学术经验。然而,我无法发现我的推理中的漏洞,所以我希望你们都能找到,以便我可以继续前进。


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

还有一些附加规则:

  1. 层从最一般(底部)到最具体(顶部)堆叠
  2. 每层都有一个公共接口(抽象)
  3. 一层只能依赖于另一层的公共接口(封装)
  4. 一个层只能依赖于更通用的层(从上到下的依赖)
  5. 一个层最好依赖于它正下方的层

因此,以 Web 应用程序为例,您的应用程序层中可以有以下层(从上到下):

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

对于最终的包布局,有一些附加规则:

  • 每个包名称的根是<prefix.company>.<appname>.<layer>
  • 层的接口按功能进一步划分:<root>.<logic>
  • 层的私有实现以 private 为前缀:<root>.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。

当您使用垂直方法进行封装设计时,即首先按功能划分,然后强制所有构建块具有不同的功能levels的功能融入到同一个“功能夹克”中。您可以为更具体的模块设计通用模块。但这违反了更一般的层不应该了解更具体的层的重要原则。例如,服务层不应按照应用程序层的概念进行建模。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

您在 Java 项目中使用什么策略进行包命名?为什么? [关闭] 的相关文章

随机推荐

  • 创建 Rally 测试文件夹时出现 .Net Rally.RestApi 错误“未授权执行操作:无效密钥”

    我有一个 C 应用程序 使用 NET 的 Rally Rest API 2 0 1 0 版 应用程序将成功查询 Rally 数据 但当我尝试创建对象时 返回错误 指示密钥无效 此问题从今天开始 并且该应用程序的多个用户都会出现此问题 我使用
  • 为什么 instanceof 不能与 JPanel 和 JComponent 一起使用?

    我觉得我在这里错过了一些非常明显的东西 对于 Java 大师来说是很容易实现的目标 我的代码如下所示 private static void myFunc JComponent c if c instanceof JPanel stuff
  • Java 货币库 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么条件变量不可 MoveAssignable

    为什么是一个condition variable不可移动构造 根据http en cppreference com w cpp thread condition variable http en cppreference com w cpp
  • 从父应用程序重新打开 Rails 3 引擎类

    就目前而言 您无法重新打开引擎中包含的引擎类 app只需在父应用程序的目录中添加相同的类即可 app目录 例如 my engine app controllers users controller rb my app app control
  • Laravel 5.4 升级 - 违反完整性约束 - 列不能为空

    奇怪的是 所有这些都在 5 2 中工作 但我不知道可以改变什么来实现这一点 下面是错误和正在插入的数组 SQLSTATE 23000 Integrity constraint violation 1048 Column gender can
  • R 中按时间划分的平均值

    我每秒测量一次化合物浓度 我想求 30 秒和 60 秒的平均值 我一直在阅读这里的帖子 我尝试过lubridate and dplyr 但没有运气 我正在努力完成这项工作 但我一直没能做到 我正在从 SAS 过渡到 R 所以请耐心等待 这是
  • 如何检查 FTP 目录是否存在

    寻找通过 FTP 检查给定目录的最佳方法 目前我有以下代码 private bool FtpDirectoryExists string directory string username string password try var r
  • 端点按资源 swagger 注释分组?

    我正在使用 Spring 进行 REST API 开发 我有一些 API 其中有很多端点 当我打开 swagger ui 时 它看起来很拥挤 我刚刚读过this https swagger io docs specification gro
  • 用于字数计算的 Swift String 中的字数

    我想做一个程序来找出字符串中有多少个单词 用空格 逗号或其他字符分隔 然后把总数加起来 我正在制作一个平均计算器 所以我想要数据总数 然后将所有单词相加 update Xcode 10 2 x Swift 5 或更高版本 使用基础方法enu
  • Bluemix 负载均衡器算法

    使用什么算法来平衡 Bluemix 上运行的多个实例之间的 HTTP 负载 看来我可以使用自动伸缩服务来水平扩展 想知道平衡负载时使用什么算法 Cloud Foundry 使用循环负载平衡在应用程序的运行实例之间分配请求
  • 插入具有多个值的外键

    我想知道 是否有可能创建一个表 其中我有一个接受外键但同一行可能有多个值的表 例如 Employee id name skillid Skill Skillid skillname 这里 Employee 的一个例子可以是 Employee
  • 为什么 C# 4.0 中的可选参数需要编译时常量?

    还有一种方法可以使用可选方法参数的运行时值吗 可选参数必须是常量 因为它们是作为属性值写出的 因此 它们继承了属性值所具有的所有限制 无法直接对运行时值进行编码 但是您可以接近以下模式 public void MyApi SomeType
  • Grails transactionManager 运行时出现异常

    当编译一个grails v2 3 3项目运行项目时出现以下错误Netbeans 7 4 Loading Grails 2 3 3 Configuring classpath Configuring classpath Environment
  • R 将多个值与向量进行比较并返回向量[重复]

    这个问题在这里已经有答案了 我有一个向量 A 对于 A 的每个元素 我想检查它是否等于第二个向量 Targets 中的任何元素 我想要一个逻辑值向量 其长度为 A 作为返回 也提到了同样的问题here http r 789695 n4 na
  • 更改 Firefox 插件安装图标

    我正在开发一个 Firefox 插件 使用附加 SDK https addons mozilla org en US developers docs sdk 1 0 dev guide welcome html 我更改了 package j
  • bigquery DataFlow 错误:在 EU 中读写时无法在不同位置读写

    我有一个简单的 Google DataFlow 任务 它从 BigQuery 表中读取数据并写入另一个表 如下所示 p beam io Read beam io BigQuerySource query select dia import
  • dplyr 返回每个组的全局平均值,而不是每个组的平均值

    有人可以解释一下我在这里做错了什么 library dplyr temp lt data frame a c 1 2 3 1 2 3 1 2 3 b c 1 2 3 1 2 3 1 2 3 temp gt group by temp 1 g
  • 检查外部 JS 库是否已加载[重复]

    这个问题在这里已经有答案了 我当前的设置是用户单击链接来动态加载内容 其中还包括加载脚本 我希望能够测试是否加载了外部脚本 特别是 Google Maps JS API 如果没有加载 则继续执行此操作 这是我的代码 if href cont
  • 您在 Java 项目中使用什么策略进行包命名?为什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我不久前就想过这个问题 最近当我的商店正在开发第一个真正的 Java Web 应用程序时 这个问题又重新出现了 作为介绍 我看到两个主要的包命名