太多的导入垃圾邮件我的代码

时间:2011-12-13 07:25:51

标签: java coding-style import package

在我的项目中,我有一个shapes包,其中包含我为我的图形程序设计的形状,例如Rectangle,Circle。我还有一两个与java.awt类名称相同的包。

现在,因为我不想重命名我的代码库中的每个类,为了向我的源文件显示我所说的类,当我声明一个新的Rectangle时,我需要:

  

1-明确导入矩形类,即import shapes.Rectangle

OR

  

2-只导入我需要的java.awt类,而不导入java.awt。*,它自动包含awt.Rectangle

现在的问题是两种方式导致很多导入,我目前在每个源文件中平均有15-25个导入,这严重影响了我的代码混乱和混乱。

代码中的导入太多是件坏事吗?有没有办法解决这个问题?

8 个答案:

答案 0 :(得分:9)

是的,过多的导入是一件坏事,因为它会使您的代码变得混乱,导致您的导入更不易读。

使用通配符避免长导入列表。

Kevlin Henney在2017年1月16日至20日在伦敦NDC会议上的演讲Clean Coders Hate What Happens to Your Code When You Use These Enterprise Programming Tricks中讨论了这个确切的Stack Overflow问题27:54

答案 1 :(得分:5)

  • 按类导入而不是导入整个包是一个好习惯

  • 任何好的IDE,例如 Eclipse ,都会在一行中折叠导入,并且您可以在需要时展开它们,这样它们就不会使您的视图混乱

    < / LI>
  • 如果发生冲突,您可以始终引用完全限定的类,但如果您控制的是这两个类中的一个,则可以考虑重命名。 (使用Eclipse,右键单击该类,选择Refactor -> Rename,将更新其所有引用)。

  • 如果您的班级是从AWT和您的形状包导入的,那就没问题。可以从几个类导入;但是,如果你发现自己从很多不同的来源进口,这可能表明你的班级做得太多了,需要分开。

答案 2 :(得分:3)

另一种方法是根据需要键入完全限定的类名。在我的示例中,有2个Element对象,一个由我org.opensearch.Element创建,另一个org.w3c.dom.Element

要解决名称冲突,以及尽量减少导入&#34;混乱&#34;,我已完成此操作(在我的org.opensearch.Element课程中):

public org.w3c.dom.Element toElement(org.w3c.dom.Document doc) { /* .... */ }

如您所见,返回Element类型是完全类型的(即我已指定完全限定的类名Element)。

问题解决了! : - )

答案 3 :(得分:2)

在Java世界中进行大量导入是正常的 - 您确实需要导入所有内容。但是如果您使用Eclipse之类的IDE,它会为您执行导入。

答案 4 :(得分:2)

我没有在此处发布所有未回答的内容。

是的,单独导入是一个坏主意,并且几乎没有增加任何价值。

相反只是显式导入与您要使用的类的冲突(编译器会告诉您awtshapes包之间的冲突。),如下所示:

import java.awt.*;
import shapes.*;
import shapes.Rectangle; // new Rectangle, and Rectangle.xxx will use shapes.Rectangle.

自Java 1.2开始,使用awtutil List类已经完成了多年。如果您偶尔要使用java.awt.Rectangle,请使用完整的类名,例如new java.awt.Rectangle(...);

答案 5 :(得分:2)

这是主观的,在很大程度上取决于具体情况。我有时会在两者之间跳动。

一般情况下,默认情况下进行特定设置是一种很好的做法,但也可以提高维护水平。这不是一个完美的规则。但是,更具体(较高的初始成本)将倾向于通过可测量的或可感知的阻力更早地展现自己,而默认情况下的懒惰往往会更不利地表现为问题。

过度包含整个名称空间会造成膨胀和冲突,并隐藏结构更改,但在某些情况下,它可能会超过收益。

举一个简单的例子:

我使用了一百个类的软件包。

  • 如果我使用其类别之一怎么办?
  • 如果我只使用其中之一,该怎么办?

这类似于白名单与黑名单问题。

在理想情况下,包装层次结构将细分包装类型,足以建立良好的平衡。

在某些系统中,我看到人们做的事情相当于import *。也许最恐怖的情况是当我看到某人做与apt install *类似的事情。尽管它看上去很聪明,所以不必担心缺少依赖关系,但它却带来了巨大的负担,远远超过了任何好处。

所有事物都可以发挥到极致。例如,我可以为导入的实用性争取尽可能接近的需要,但是如果我们要这样做,为什么不总是一直使用完全限定名称呢?

像这样的问题很烦人,因为始终如一的低认知负荷总是可取的,但是当在各种给定情况下归结为低负荷时,您可能需要亲耳聆听。

保持比例很重要。做一千次以避免一次出现的事情,自我呈现出来并花费大量的精力进行修复往往会导致浪费。

不同的目标可能会使“太多”的进口商品成为好东西。我有一个自定义的JavaScript框架,对于它的导入堆栈,乍一看可能会使许多人感到恐惧。

现在还不是很明显,这是蓄意战略的一部分。

  • 这使得轻松完成代码及其所有特定依赖项的打包工作,然后通过网络进行传输变得容易。
  • 导入在构建时具有插件性质,可以为每个给定的平台目标替换依赖项。

对于那些动态性较差并且不会因过度导入名称空间而造成的开销(或根本没有受到很大影响)的语言,这往往不是问题。这个故事的寓意是,进口策略可以有很大的不同,但在特定情况下是有效的。您只能采取一般方法。

在每种情况下,您都需要掌握方位和对土地的了解。如果导入约定和结构造成麻烦,则必须缩小操作方式和原因。导入过多可能不是特定策略的结果,而是将太多内容打包到一个文件中。同时,某些文件自然会很大,自然需要进行很多导入。

如果未能将相关事物放在一起,则对问题或组织的错误应用会造成图表严重边缘化,而如果组织化程度更高,则可以减少这种情况。在某种程度上,通过特定的依赖关系对代码进行聚类并不比正常情况更为普遍。

如果代码库被很好地组织成一个非常接近最优的图形,并且没有过多的拆分,合并和事物之间的最小距离,那么您将趋向于发现,即使特定于导入,大多数情况也倾向于保留。在合理的尺寸之内。

答案 6 :(得分:1)

  • 如果使用glob导入,则仅通过更新引入新类型的依赖项(通常不希望有重大改变)就可以用名称空间冲突来破坏代码。在使用glob导入的自由的大型代码库中进行修复可能会很痛苦。这是我能想到的最有力的理由,为什么明确指定依赖项是一个好主意。
  • 阅读指定了每个导入的代码更容易, 因为您无需IDE就可以查看类型的来源 特定功能和鼠标悬停,或浏览库文档的大页面。许多人在IDE之外阅读了很多代码,包括代码审查,差异,git历史记录等。

答案 7 :(得分:0)

我使用显式导入,并且已经这样做了很多年。在我过去十年的所有项目中,团队成员都同意这一点,并且所有人都乐于同意使用显式导入并避免通配符。没有争议。

支持显式导入:

  • 精确定义使用哪些类
  • 随着代码库的其他部分发生变化而变得不那么脆弱
  • 更容易进行代码审查
  • 不用猜测哪个类在哪个包中

支持通配符:

  • 更少的代码
  • 使用文本编辑器时更容易添加和维护导入

在我职业生涯的早期,我确实使用了通配符导入,因为那时 IDE 还没有那么复杂,或者我们中的一些人只是使用文本编辑器。手动管理显式导入相当费力,因此通配符导入确实很有帮助。

然而,至少有一次我被通配符导入的使用所困扰,这导致我目前的政策是仅显式。

假设您有一个包含 10 个通配符导入的类,并且它编译成功。然后您将 5 个 jar 文件升级到较新的版本(您必须将它们全部升级,因为它们是相关的)。然后代码不再编译,出现类未找到错误。现在那个类在哪个包中?班级的全名是什么?我不知道,因为我只使用短名称,现在我必须区分 jars 的旧版本和新版本,看看有什么变化。

如果我使用了显式导入,就会清楚哪个类被删除了,它的包是什么,以及哪个 jar(通过查看该包中的其他类)负责。

阅读代码历史或查看历史合并也存在问题。当您使用通配符导入时,读者不确定哪个类是哪个,因此代码更改的语义是什么。通过显式导入,您可以获得对代码的精确描述,它可以作为更好的历史记录。

因此,总体而言,为维护导入而付出的少量额外工作和额外代码行的好处很容易被显式导入提供的额外精度和确定性所抵消。

我仍然使用通配符的唯一情况是从同一个包中导入超过 50 个。这种情况很少见,通常只用于常量。