如何命名您创建的不同类/接口?
有时我没有要添加到实现名称的实现信息 - 比如接口FileHandler
和类SqlFileHandler
。
当发生这种情况时,我通常将该界面命名为“普通”名称,例如Truck
,并命名实际的类TruckClass
。
如何在这方面命名接口和类?
答案 0 :(得分:821)
为您的Interface
命名。 Truck
。不是ITruck
,因为它不是ITruck
,而是Truck
。
Java中的Interface
是Type。然后,您DumpTruck
,TransferTruck
,WreckerTruck
,CementTruck
等implement Truck
。
当您使用Interface
代替子类时,您只需将其转换为Truck
。与List<Truck>
中一样。将I
放在前面只是Hungarian style符号tautology,它只会为您的代码添加更多内容。
所有现代Java IDE都标记了接口和实现以及没有这种愚蠢符号的东西。不要将TruckClass
称为tautology,与IInterface
重言式一样糟糕。
如果它是一个实现它是一个类。这个规则唯一真正的例外,总有例外,可能是AbstractTruck
。由于只有子类才能看到这个,并且你永远不应该转换为Abstract
类,它确实会添加一些类是抽象的信息以及如何使用它。您仍然可以提供比AbstractTruck
更好的名称,并使用BaseTruck
或DefaultTruck
,因为abstract
位于定义中。但由于Abstract
类永远不应成为任何面向公众的界面的一部分,我认为这是规则的可接受的例外。使构造函数protected
在很大程度上跨越了这个鸿沟。
Impl
后缀也是更多的噪音。更多的重言式。任何不是接口的东西都是一个实现,甚至是部分实现的抽象类。你是否会在每个Class的每个名字上加上那个愚蠢的Impl
后缀?
Interface
是关于公共方法和属性必须支持的合同,它也是Type信息。实现Truck
的所有内容都是Truck
IList
。
查看Java标准库本身。您看到ArrayListImpl
,LinkedListImpl
,List
了吗?不,您看到ArrayList
和LinkedList
以及DTO
。关于这个确切的问题,这是一个很好的Type。任何这些愚蠢的前缀/后缀命名约定都违反了article原则。
此外,如果您发现自己向对象添加了JDO
,BEAN
,Class
或其他愚蠢的重复后缀,那么它们可能属于DRY而不是所有这些后缀。正确打包的命名空间是自我记录的,并且减少了这些非常缺乏构思的专有命名方案中的所有无用的冗余信息,大多数地方甚至没有以一致的方式内部遵守这些命名方案。
如果您只想提出Impl
名称的唯一名称后缀为Interface
,那么您需要重新考虑拥有Interface
。 因此,当您遇到Implementation
和Interface
的情况时,Interface
并不是唯一专业的,您可能不需要{{1}} 强>
答案 1 :(得分:95)
我在这里看到的答案表明,如果你只有一个实现,那么你不需要一个接口。面对Depencency Injection / Inversion of Control原则(不要打电话给我们,我们会打电话给你!)。
所以是的,在某些情况下,您希望通过依赖注入的接口实现(也可能代理 - 您的代码不知道!)来简化代码并使其易于测试。即使你只有两个实现 - 一个是用于测试的模拟,另一个是注入到实际的生产代码中 - 这不会使界面变得多余。一个记录良好的接口建立了一个合同,也可以通过严格的模拟实现进行维护以进行测试。
实际上,你可以建立测试,让mocks实现最严格的接口契约(抛出不应为null的参数的异常等)并在生产代码中使用更有效的实现来捕获测试中的错误(不检查因为模拟在测试中抛出异常而你知道由于在这些测试之后修复代码,因此参数不为null,所以参数不应该为null为空。
依赖注入/ IOC对于新手来说很难掌握,但是一旦你理解了它的潜力,你就会想要在整个地方使用它,你会发现自己一直在进行接口 - 即使只有是一个(实际生产)实施。
对于这个实现(你可以推断,你是对的,我相信测试的模拟应该被称为Mock(InterfaceName)),我更喜欢名称Default(InterfaceName)。如果出现更具体的实现,则可以适当地命名。这也避免了我特别不喜欢的Impl后缀(如果它不是一个抽象类,那么它是一个“impl”!)。
我也更喜欢“Base(InterfaceName)”而不是“Abstract(InterfaceName)”,因为在某些情况下你希望你的基类以后变得可实例化,但现在你仍然坚持使用名称“Abstract( “InterfaceName)”,这会强制你重命名该类,可能会造成一点点混淆 - 但如果它总是Base(InterfaceName),则删除abstract修饰符不会改变类的含义。
答案 2 :(得分:60)
接口的名称应描述接口所代表的抽象概念。任何实现类都应该具有某种特定的特征,可以用来为它提供更具体的名称。
如果只有一个实现类,你不能想到任何使它具体化的东西(暗示想要命名为-Impl
),那么看起来没有任何理由可以拥有一个接口
答案 3 :(得分:31)
我倾向于遵循Java Core / Sun建立的伪约定,例如在Collections类中:
List
- “概念”对象的界面ArrayList
- 接口的具体实现LinkedList
- 接口的具体实现AbstractList
- 抽象的“部分”实现以协助自定义实现我曾经在AWT事件/侦听器/适配器范例之后对事件类建模做同样的事情。
答案 4 :(得分:28)
标准的C#约定,在Java中运行良好,是为所有接口添加I
前缀 - 所以你的文件处理程序接口将是IFileHandler
,你的卡车接口将是{{1 }}。它是一致的,并且可以很容易地从类中分辨出接口。
答案 5 :(得分:21)
我喜欢用于指示接口所描述的合约的接口名称,例如“Comparable”或“Serializable”。像“卡车”这样的名词并不能真正描述卡车 - 卡车的能力是什么?
关于约定:我参与了每个界面以“I”开头的项目;虽然这与Java约定有些陌生,但它使查找界面非常容易。除此之外,“Impl”后缀是一个合理的默认名称。
答案 6 :(得分:9)
有些人不喜欢这样,它更像是.NET约定而不是Java,但你可以使用大写字母I前缀来命名接口,例如:
IProductRepository - interface
ProductRepository, SqlProductRepository, etc. - implementations
反对这种命名惯例的人可能会争辩说你不应该关心你是在使用代码中的接口还是对象,但我发现它更容易在运行中阅读和理解。
我不会将实现类命名为“Class”后缀。这可能会导致混淆,因为您实际上可以在代码中使用“类”(即Type)对象,但在您的情况下,您不使用类对象,您只是使用一个普通的对象
答案 7 :(得分:1)
TruckClass
听起来像是一类Truck
,我认为推荐的解决方案是添加Impl
后缀。在我看来,最好的解决方案是在实现名称中包含一些信息,在特定实现中发生了什么(就像我们使用List
接口和实现:ArrayList
或LinkedList
),但是有时您只有一个实现,并且由于远程使用而必须具有接口(例如),然后(如开头所述)Impl
是解决方案。
答案 8 :(得分:1)
我使用两种惯例:
如果接口是一个众所周知的模式的特定实例(例如Service,DAO),那么它可能不需要“I”(例如UserService,AuditService,UserDao)在没有“I”的情况下都可以正常工作,因为post-fix确定元模式。
但是,如果您有一次性或两次性(通常用于回调模式),则有助于将其与类(例如IAsynchCallbackHandler,IUpdateListener,IComputeDrone)区分开来。这些是专为内部使用而设计的专用接口,偶尔会让IInterface注意到操作数实际上是一个接口的事实,所以乍一看它很快就会清楚。
在其他情况下,您可以使用I来避免与其他常见的具体类(ISubject,IPrincipal vs Subject或Principal)发生冲突。