Java接口/实现命名约定[重复]

v09wglhw  于 2023-05-21  发布在  Java
关注(0)|答案(9)|浏览(107)

此问题已在此处有答案

Interface naming in Java [closed](11个回答)
7年前关闭。
如何命名您创建的不同类/接口?有时候我没有实现信息可以添加到实现名称中,比如接口FileHandler和类SqlFileHandler
当这种情况发生时,我通常将接口命名为“正常”名称,如Truck,并将实际的类命名为TruckClass
在这方面,你如何命名接口和类?

vybvopom

vybvopom1#

Interface是什么不是ITruck,因为它不是ITruck,而是Truck
Java中的InterfaceType。然后你有DumpTruckTransferTruckWreckerTruckCementTruckimplements Truck
当你使用Interface来代替一个子类时,你只需要将它转换为Truck。如List<Truck>。把I放在前面只是Systems Hungarian style符号tautology,它只会增加更多的东西来输入代码。
所有现代Java IDE的标记接口和实现等都没有这个愚蠢的符号。不要称之为TruckClass,它是tautology,就像IInterface同义反复一样糟糕。
如果它是一个实现,它就是一个类。这条规则的唯一真实的的例外,总是有例外,可能是像AbstractTruck这样的东西。因为只有子类会看到这个,你永远不应该转换到Abstract类,它确实添加了一些信息,该类是抽象的,应该如何使用。您仍然可以想出一个比AbstractTruck更好的名称,并使用BaseTruckDefaultTruck,因为abstract在定义中。但是由于Abstract类不应该是任何面向公共接口的一部分,我相信这是一个可以接受的例外。创建构造函数protected对于跨越这一鸿沟有很大帮助。
后缀Impl也只是更多的噪音。更多的同义反复。任何不是接口的东西都是实现,即使是部分实现的抽象类。你打算把那个愚蠢的Impl后缀放在每个Class的每个名字上吗?
Interface是一个关于公共方法和属性必须支持的契约,它也是Type信息。所有实现Truck的东西都是TruckType
查看Java标准库本身。你看到IListArrayListImplLinkedListImpl了吗?不,你看到的是ListArrayList,还有LinkedList。这里有一个很好的article关于这个确切的问题。任何这些愚蠢的前缀/后缀命名约定都违反了DRY原则。
此外,如果你发现自己添加DTOJDOBEAN或其他愚蠢的重复后缀到对象,那么它们可能属于package而不是所有这些后缀。正确打包的名称空间是自文档化的,并减少了这些构思非常糟糕的专有命名方案中所有无用的冗余信息,大多数地方甚至在内部都没有以一致的方式遵守这些命名方案。
如果您能想到的使Class名称唯一的方法是使用Impl作为后缀,那么您需要重新考虑是否使用Interface。因此,当您有一个Interface和一个不是从Interface唯一专用化的Implementation时,在大多数情况下可能不需要Interface
然而,一般来说,为了可维护性、可测试性和模拟,最好的做法是提供接口。参见this answer for more details
另请参考Martin Fowler关于InterfaceImplementationPair主题的有趣文章

3bygqnnd

3bygqnnd2#

我在这里看到的答案表明,如果你只有一个实现,那么你就不需要接口。这与依赖注入/控制反转原则背道而驰(不要打电话给我们,我们会打电话给你!).
所以,是的,在某些情况下,你希望简化你的代码,并通过依赖注入的接口实现(这也可能是代理的-你的代码不知道!即使您只有两个实现-一个是用于测试的Mock,另一个是注入到实际生产代码中的-这也不会使接口变得多余。一个有良好文档记录的接口建立了一个契约,它也可以由一个严格的模拟实现来维护以进行测试。
事实上,您可以建立让模拟实现最严格接口约定的测试(为不应为null的参数抛出异常等)并捕获测试中的错误,在生产代码中使用更有效的实现(不检查不应该为null的参数是否为null,因为mock在测试中抛出了异常,并且您知道这些参数不是null,因为在这些测试之后修复了代码,例如)。
对于新手来说,依赖注入/IOC可能很难掌握,但是一旦你了解了它的潜力,你就会想在所有地方使用它,你会发现自己一直在制作接口--即使只有一个(实际生产)实现。
对于这个实现(您可以推断,并且您是正确的,我认为用于测试的mock应该称为Mock(InterfaceName)),我更喜欢名称Default(InterfaceName)。如果沿着更具体的实现,可以适当地命名。这也避免了我特别不喜欢的Impl后缀(如果它不是一个抽象类,当然它是一个“impl”!).
我也更喜欢“基地(InterfaceName)”而不是“Abstract(InterfaceName)”,因为在某些情况下,您希望基类以后成为可示例化的,但现在您被名称“Abstract”卡住了(InterfaceName)",这会迫使您重命名类,可能会引起一点小混乱-但如果它总是Base(InterfaceName),移除抽象修饰符不会改变类的性质。

5us2dqdw

5us2dqdw3#

接口的名称应该描述接口所代表的抽象概念。任何实现类都应该有某种特定的特征,可以用来给予它一个更具体的名字。
如果只有一个实现类,并且您想不出任何使其特定的东西(希望将其命名为-Impl),那么看起来根本没有理由拥有接口。

uhry853o

uhry853o4#

我倾向于遵循Java Core/Sun建立的伪约定,例如。在集合类中:

  • List-“概念”对象的接口
  • ArrayList-接口的具体实现
  • LinkedList-接口的具体实现
  • AbstractList-抽象的“部分”实现,以协助自定义实现

我以前也做过同样的事情,在AWT事件/监听器/适配器范例之后对我的事件类进行建模。

eqoofvh9

eqoofvh95#

标准的C#约定(在Java中也很好用)是在所有接口前面加上I-因此您的文件处理程序接口将是IFileHandler,卡车接口将是ITruck。它是一致的,并且很容易区分接口和类。

ie3xauqp

ie3xauqp6#

我喜欢用接口名来表示接口描述的合约,比如“Comparable”或“Serializable”。像“卡车”这样的名词并不能真正描述卡车的特性--卡车的能力是什么?
关于公约:我曾经参与过的项目中,每个界面都以“I”开头;虽然这与Java约定有些不同,但它使查找接口变得非常容易。除此之外,“Impl”后缀是一个合理的默认名称。

um6iljoc

um6iljoc7#

有些人不喜欢这样,它更像是一个.NET约定而不是Java,但你可以用大写的I前缀命名你的接口,例如:

IProductRepository - interface
ProductRepository, SqlProductRepository, etc. - implementations

反对这种命名约定的人可能会争辩说,你不应该关心你在代码中是使用接口还是对象,但我发现它更容易阅读和理解。
我不会用“Class”后缀来命名实现类。这可能会导致混淆,因为您实际上可以使用“类”(即类型)对象,但在您的示例中,您不是在处理类对象,而是在处理一个普通的旧对象。

wa7juj8i

wa7juj8i8#

我使用这两种约定:
如果接口是一个众所周知的模式的特定示例(例如服务,DAO),那么它可能不需要“I”(例如UserService,AuditService,UserDao),所有没有“I”的工作都很好,因为后缀决定了 meta模式。
但是,如果你有一些一次性或一次性的东西(通常是一个回调模式),那么它有助于将它与一个类区分开来(例如。IAsynchCallbackHandler、IUpdateListener、IComputeDrone)。这些是为内部使用而设计的特殊用途接口,有时IInterface会引起注意,操作数实际上是一个接口,因此乍一看很清楚。
在其他情况下,您可以使用I来避免与其他常见的具体类(ICubber,IPrincipal vs Subject或Principal)发生冲突。

kx7yvsdv

kx7yvsdv9#

TruckClass听起来像是Truck的一个类,我认为推荐的解决方案是添加Impl后缀。在我看来,最好的解决方案是在实现名称中包含一些信息,在特定的实现中发生了什么(就像我们在List接口和实现中所做的那样:ArrayListLinkedList),但有时您只有一个实现,并且由于远程使用(例如)而必须具有接口,那么(如开头所述)Impl就是解决方案。

相关问题