java包装项目
程序包是Java的基本概念,是您开始用该语言编程时偶然发现的第一件事。 作为一个初学者,您可能不太关注软件包的结构,但是随着您成为经验丰富且成熟的软件开发人员,您开始考虑可以采取哪些措施来提高其效率。 有几个主要选项需要考虑,选择正确的选项可能不是一个显而易见的选择。 本文应该为您提供常用策略的概述。
我们为什么使用包裹?
从语言的角度来看,Java包提供了两个重要的功能,编译器可以利用它们。 最明显的一个是类的名称空间定义。 几个名称完全相同的类可以在一个项目中使用,只要它们属于不同的包即可将一个类与另一个类区分开。 如果您无法想象如果没有包,该语言将是什么样子,那么请看一下JavaScript世界中的模块化策略。 在ES2015之前,没有官方标准,而且命名冲突并非罕见。
第二件事是,程序包允许为项目的特定成员定义访问修饰符。 对于不同包的成员,可以限制或完全禁止类,接口或其成员(如字段和方法)的可访问性。
编译器首先使用这两个功能来实施语言规则。 对于干净的编码人员和软件技术人员而言,软件包的主要属性可能具有有意义的名称,该名称描述了软件包的用途和存在的原因。 对于编译器,这只是一个随机的char字符串,而对于我们来说,这是表达我们意图的另一种方式。
什么是包裹?
在官方的Java教程中,我们可以找到以如下形式开头的定义:
程序包是一个命名空间,用于组织一组相关的类和接口。 从概念上讲,您可以将软件包视为类似于计算机上的不同文件夹。 您可以将HTML页面保留在一个文件夹中,将图像保留在另一个文件夹中,并将脚本或应用程序保留在另一个文件夹中。 (...)
第一句话强调软件包的组织目的。 但是,该定义并未说明应将哪种关系类和接口视为一个单独的组。 这个问题向所有软件开发人员开放。 最近,肯特·贝克(Kent Beck)写了一条一般性建议,该建议也适用于本文中讨论的主题:
如果您一直想知道该如何清理,请将相似的元素移到更近的位置,并将不同的元素移到更远的位置
-肯特·贝克(@KentBeck) 2017年6月26日
但是,就像上述包装定义中的“相关”一词一样,“相似”一词对不同的人可能具有完全不同的含义。 在本文的其余部分,我们将在软件包组织的背景下考虑可能的选择。
逐层包装
项目类之间最普遍公认的相似之处可能是他们的责任。 使用此属性进行组织的方法称为逐层打包或水平切片,实际上,其外观或多或少类似于下图。
如果您没有机会从事具有这种结构的项目,则可以在一些框架教程中找到它。 例如,Play框架建议在2.2版之前使用这种方法。 Angular.js的教程最初建议根据其职责将事物保持在一起。
他们改变了对主题的看法,并更新了教程,这可能会让您思考是什么原因。 但是在判断解决方案之前,让我们先看一下它的优缺点。
优点
考虑到分层体系结构是使用最广泛的体系结构,开发人员旨在在包结构中反映所选体系结构也就不足为奇了。 这种方法的长期流行会影响将结构应用到新项目中的决定,因为团队的新手更容易在他们熟悉的环境中采用他们。
在此类应用程序中为新类找到合适的位置实际上是理所当然的操作。 该结构是在开发之初创建的,并且在整个项目存在期间都保持不变。 这种简单性使得即使经验不足的开发人员也可以使项目保持秩序,因为结构易于理解。
缺点
有人说将所有模型类放在一个位置使它们更易于重用,因为它们可以与整个包一起简单地复制到另一个项目中。 但是真的是这样吗? 特定域模型的形状通常仅在项目内的有限上下文中有效。 例如,产品类别在购物应用程序中将具有与管理制造商订单的应用程序不同的属性。 即使您想使用相同的类,也有必要将它们提取到每个应用程序中标记为依赖项的单独jar中。 即使存在于独立但相关的项目中,代码重复也会导致错误,因此我们应避免粘贴粘贴。
逐层打包方法的主要缺点是过度使用了公共访问修饰符。 现代的IDE默认情况下使用public修饰符创建类和方法,而不会强迫开发人员考虑使用更合适的选项。 实际上,在分层包组织中没有其他选择。 仅将存储库公开给单个服务类,就要求该存储库是公共的。 副作用是,项目中的所有其他类都可以访问该存储库,即使是不应该与其直接通信的层也可以访问该存储库。 这种方法鼓励创建无法维护的意大利面条代码,并导致包装之间的高度耦合。
如今,无论它们在何处,都可以在IDE中的已连接类之间轻松切换,但为新功能添加新的类集需要更多的注意。 当类分布在多个目录中时, 仅通过查看代码也很难评估功能的复杂性 。
一开始,我们说过程序包的名称应提供有关其内容的其他详细信息。 在逐包方法中,所有程序包都描述了解决方案的体系结构,但是它们分别没有提供任何有用的信息。 实际上,在许多情况下,它们会复制其成员的类名中显示的信息。
按功能包装
在硬币的另一面,您可以围绕要素或领域模型构建类。 您可能已经听说过这种方法是垂直切片组织。 如果仅使用水平切片,乍一看可能看起来有些混乱,但是最后这只是心态问题。 下图表示与上一段相同的类,但包装布局不同。
您可能不会仅仅因为左脚适合同一只脚而将所有左脚鞋放在一个位置,而另一只脚就放在另一位置。 您要成对穿着鞋子,因为那是您使用鞋子的方式。 同样,您可以查看项目中的类。
垂直切片的核心思想是将构建特定功能的所有类放在单个程序包中。 遵循此规则,您将获得一些好处,但同时也会面临一些负面后果。
优点
当所有要素类都放在一个程序包中时,public access修饰符更具表现力,因为它允许描述要素的哪一部分应由应用程序的其他部分访问。 在包内,您应该赞成使用package-private修饰符来改善模块化。 最好在IDE中修改默认模板,以避免创建公共类和方法。 公开一些东西应该是一个有意识的决定。 来自不同程序包的类之间较少的连接将导致更简洁,更可维护的代码库。
在水平切片中,程序包在每个项目中具有相同的名称集,而在垂直切片方法中, 程序包具有更有意义的名称,这些名称描述了它们的功能用途 。 仅通过查看项目结构,您就可以猜测用户可以使用该应用程序做什么。 该方法还表达了要素之间的层次关系。 域的聚合根很容易识别,因为它们存在于程序包树的最低层。 包结构记录了应用程序。
根据功能对类进行分组可以使程序包更小,更容易浏览。 在横向方法中,每个新功能都会增加图层包中类的总数,并使它们更难浏览。 在长长的类列表中找到有趣的元素将成为一种低效率的活动。 相比之下, 仅当扩展了功能时 , 关注该功能的软件包才会增长 。 新功能在树的适当节点中接收其自己的包。
还值得一提的是垂直切片包装的灵活性。 随着微服务架构的日益普及,拥有已经按功能分割的整体应用程序绝对比将项目按层组织的项目更容易转换成单独的服务。 采用按功能打包的方法可以为应用程序的可扩展性增长做好准备。
缺点
随着项目的发展,软件包的结构需要更多的注意。 重要的是要了解,随着应用程序变得越来越复杂,程序包树会随着时间而发展。 您有时会不得不停一会儿,并考虑将程序包移动到其他节点或将其拆分为较小的节点。 结构的清晰度不是免费的。 团队负责保持其良好状态,并与该领域的知识保持一致。
了解领域是清洁项目结构的关键要素。 为新功能选择合适的位置可能会遇到问题,特别是对于团队新手来说,因为这需要您应用程序背后的业务知识。 某些人可能会认为这是一种优势,因为这种方法鼓励团队成员之间共享知识。 向该项目介绍新的开发人员比较耗时,但可能会被视为一项投资。
混合方式
您可能认为四肢没有好处。 我们难道不能仅从两种方法中取最大的优点,并创造介于两个极端之间的新质量吗? 有两种可能的组合。 程序包的第一层被一层划分,要素是它们的子级,要素建立在顶层,层是它们的子节点。
第一种选择是您可能遇到的,因为它是增长到大尺寸包装的常见解决方案。 它增加了结构的清晰度,但是不幸的是,逐层封装方法的所有缺点都像以前一样适用。 最大的问题是,仍然必须在几乎所有地方都使用public修饰符,以连接您的类和接口。
使用另一个选项,我们应该问一个问题,该解决方案是否真的有意义。 按功能打包的方法支持层的组织,但它是在类级别上而不使用package的 。 通过引入其他级别的软件包,我们将失去利用默认访问修饰符的能力。 我们在结构上也没有获得太多简化。 如果功能包增长到难以管理的大小,则提取子功能可能更好。
摘要
在开始新项目时,选择包结构是您必须要做的第一选择。 该决定会影响整个解决方案的未来可维护性。 尽管从理论上讲,您可以在任何时间点更改方法,但是通常,这种转移的总成本只会阻止这种转移的发生。 这就是为什么在开始时与整个团队花费几分钟并比较可能的选择尤为重要的原因。 一旦做出选择,您要做的就是确保每个开发人员都遵循相同的策略。 对于按功能打包的方法来说,这可能会比较困难,特别是如果是第一次使用,但是好处列表绝对值得努力。
如果您对垂直切面有任何经验,并且想在主题中增加两分钱, 请随时在评论中分享您的想法 。 另外,请考虑与您的同事分享该帖子。 阅读您的讨论结果和对该方法的感受将是很棒的。
翻译自: https://www.javacodegeeks.com/2017/07/project-package-organization.html
java包装项目