Java接口/实现命名约定

Java Interfaces/Implementation naming convention

本问题已经有最佳答案,请猛点这里访问。

如何命名创建的不同类/接口?有时我没有要添加到实现名称中的实现信息,比如接口FileHandler和类SqlFileHandler

当这种情况发生时,我通常用"普通"名称命名接口,比如Truck,并将实际类命名为TruckClass

在这方面,您如何命名接口和类?


把你的名字命名为InterfaceTruck。不是ITruck,因为它不是ITruck,而是Truck

Java中的EDOCX1 3是一种类型。那么你就有DumpTruckTransferTruckWreckerTruckCementTruck等。

当您使用Interface代替子类时,您只需将其强制转换为Truck。如List所述。把I放在前面只是匈牙利风格的符号重言式,它只增加了代码类型的更多内容。

所有现代Java IDE的标记接口和实现,以及什么都没有这个愚蠢的符号。不要称之为TruckClass,这是重言式,和IInterface重言式一样糟糕。

如果它是一个实现,那么它是一个类。这条规则唯一真正的例外,而且总是有例外的,可能是类似于AbstractTruck的东西。因为只有子类才会看到这一点,并且您永远不应该将其强制转换为Abstract类,所以它确实添加了一些信息,说明类是抽象的,以及如何使用它。你仍然可以想出一个比AbstractTruck更好的名字,用BaseTruckDefaultTruck代替,因为Abstract在定义中。但是,由于Abstract类不应该是任何面向公共接口的一部分,我认为这是一个可以接受的规则例外。让建造师protected跨越这一鸿沟还有很长的路要走。

而且Impl后缀的噪音也比较大。更多重言式。任何不是接口的东西都是实现,甚至是部分实现的抽象类。你打算在每个班级的每个名字上加上这个愚蠢的Impl后缀吗?

Interface是一个公共方法和属性必须支持的契约,也是类型信息。实现Truck的一切都是Truck的一种。

查看Java标准库本身。你看到IListArrayListImplLinkedListImpl了吗?不,你看到ListArrayList,还有LinkedList。这是一篇关于这个确切问题的好文章。这些愚蠢的前缀/后缀命名约定都违反了dry原则。

此外,如果您发现自己在对象中添加了DTOJDOBEAN或其他愚蠢的重复后缀,那么它们可能属于一个包,而不是所有这些后缀。正确打包的名称空间是自文档化的,并减少了这些设计糟糕的专有命名方案中所有无用的冗余信息,而大多数地方甚至在内部都不以一致的方式遵循这些专有命名方案。

如果你所能想到的使你的Class的名字唯一的方法就是用Impl给它加上后缀,那么你需要重新考虑有一个Interface。所以,当你有一个Interface和一个Implementation,不是Interface特有的情况下,你可能不需要Interface


我在这里看到的答案表明,如果您只有一个实现,那么就不需要接口。这违背了依赖注入/控制反转的原则(不要叫我们,我们会叫你!).

所以是的,在某些情况下,您希望简化代码,并通过依赖注入的接口实现(也可能是代理的——您的代码不知道!)即使只有两种实现——一种是模拟测试,另一种是注入到实际的生产代码中——这并不意味着拥有一个多余的接口。一个有良好文档记录的接口建立了一个契约,它也可以通过一个严格的测试模拟实现来维护。

实际上,您可以建立一些测试,让mock实现最严格的接口约定(为不应为空的参数抛出异常等),并在测试中捕获错误,在生产代码中使用更有效的实现(不检查不应为空的参数,因为mock在您的测试中抛出了异常)。例如,STS和您知道参数不是空的,因为在这些测试之后修改了代码)。

依赖注入/IOC对于新手来说可能很难把握,但是一旦你了解了它的潜力,你就会想在整个地方使用它,并且你会发现自己一直在制作接口——即使只有一个(实际生产)实现。

对于这一个实现(您可以推断,而且您是正确的,我认为用于测试的模拟应该称为mock(interfacename)),我更喜欢名称default(interfacename)。如果出现更具体的实现,则可以对其进行适当的命名。这也避免了我特别不喜欢的impl后缀(如果它不是抽象类,当然它是一个"impl"!).

我也更喜欢"base(interfacename)"而不是"abstract(interfacename)",因为在某些情况下,您希望您的基类稍后变得可实例化,但现在您仍然使用"abstract(interfacename)"这个名称,这将强制您重命名该类,可能会导致一点小混乱,但如果它始终是base(interfacename),移除抽象修饰符不会改变类的内容。


接口的名称应该描述接口所代表的抽象概念。任何实现类都应该具有某种特定的特性,可以用来给它一个更具体的名称。

如果只有一个实现类,并且您不能想到任何使它具体化的东西(通过想将其命名为-Impl),那么看起来根本没有理由拥有一个接口。


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

  • List"概念"对象的接口
  • ArrayList—接口的具体实现
  • LinkedList—接口的具体实现
  • AbstractList—抽象的"部分"实现以帮助自定义实现
  • 小精灵

    我曾经在awt事件/侦听器/适配器范式之后对我的事件类进行建模。


    在Java中工作得很好的标准C.C约定是用EDCOX1(0)}对所有接口进行前缀-因此,您的文件处理程序接口将是EDCOX1×1,而您的卡车接口将是EDCOX1×2。它是一致的,并且使区分接口和类变得容易。


    我喜欢指示接口描述的契约的接口名称,例如"可比较"或"可序列化"。像"卡车"这样的名词并不能真正描述卡车的特性——卡车有什么能力?

    关于约定:我已经研究了每个接口从一个"i"开始的项目;虽然这与Java约定有点陌生,但它使得查找接口非常容易。除此之外,"impl"后缀是一个合理的默认名称。


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

    1
    2
    IProductRepository - interface
    ProductRepository, SqlProductRepository, etc. - implementations

    反对这种命名约定的人可能会争辩说,您不应该关心您在代码中使用的是接口还是对象,但我发现在运行中更容易阅读和理解。

    我不会用"class"后缀命名实现类。这可能会导致混淆,因为您实际上可以在代码中使用"class"(即type)对象,但在您的情况下,您不使用class对象,而是使用一个普通的旧对象。


    我使用两种约定:

    如果接口是一个已知模式(如服务、DAO)的特定实例,那么它可能不需要一个"i"(如用户服务、审计服务、用户DAO),没有"i"都可以正常工作,因为后缀决定了元模式。

    但是,如果您有一个或两个关闭(通常用于回调模式),那么它有助于将其与类(例如,iasynchcallbackhandler、iupdatelistener、icomputedrone)区分开来。这些是专门为内部使用而设计的接口,偶尔iInterface会引起人们对操作数实际上是接口这一事实的注意,因此乍一看就很清楚。

    在其他情况下,可以使用i来避免与其他常见的具体类(i subject、i principal、subject或principal)发生冲突。


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