你如何命名你创建的不同的类/接口? 有时我没有实现信息可以添加到实现名称中——比如接口FileHandler和类SqlFileHandler。
当这种情况发生时,我通常将接口命名为“正常”名称,如Truck,并将实际的类命名为TruckClass。
在这方面,如何命名接口和类?
你如何命名你创建的不同的类/接口? 有时我没有实现信息可以添加到实现名称中——比如接口FileHandler和类SqlFileHandler。
当这种情况发生时,我通常将接口命名为“正常”名称,如Truck,并将实际的类命名为TruckClass。
在这方面,如何命名接口和类?
当前回答
命名你的接口。卡车。不是卡车,因为它不是卡车,它是卡车。
Java中的接口是一种类型。然后你有DumpTruck, TransferTruck, WreckerTruck, CementTruck等实现了Truck。
当您使用接口代替子类时,只需将其转换为Truck即可。如List<Truck>。把I放在前面只是匈牙利风格的符号重复,它只会在代码中添加更多的东西。
所有现代Java IDE的标记接口和实现等等都离不开这个愚蠢的符号。不要叫它TruckClass,那是和IInterface一样糟糕的重述。
If it is an implementation it is a class. The only real exception to this rule, and there are always exceptions, could be something like AbstractTruck. Since only the sub-classes will ever see this and you should never cast to an Abstract class it does add some information that the class is abstract and to how it should be used. You could still come up with a better name than AbstractTruck and use BaseTruck or DefaultTruck instead since the abstract is in the definition. But since Abstract classes should never be part of any public facing interface I believe it is an acceptable exception to the rule. Making the constructors protected goes a long way to crossing this divide.
Impl后缀也是杂音。更多的同义反复。任何不是接口的东西都是实现,即使是部分实现的抽象类也是如此。你打算在每个类的每个名字上都加上那个愚蠢的Impl后缀吗?
接口是公共方法和属性必须支持的内容的契约,它也是类型信息。所有实现卡车的东西都是一种卡车类型。
看看Java标准库本身。你看到IList ArrayListImpl LinkedListImpl了吗?不,你看到的是列表和数组列表,还有LinkedList。这里有一篇关于这个问题的好文章。任何这些愚蠢的前缀/后缀命名约定都违反了DRY原则。
此外,如果您发现自己向对象添加了DTO、JDO、BEAN或其他愚蠢的重复后缀,那么它们可能属于一个包,而不是所有这些后缀。适当打包的名称空间是自文档化的,并减少了这些构思糟糕的专有命名方案中所有无用的冗余信息,大多数地方甚至在内部都没有以一致的方式坚持这些专有命名方案。
如果要使类名唯一,只能给它加上Impl的后缀,那么您需要重新考虑是否有接口。所以当你有一个接口和一个单独的实现,而不是唯一专门化的接口时,你可能在大多数情况下不需要接口。
然而,一般来说,对于可维护性、可测试性和模拟,提供接口是最佳实践。更多细节请看这个答案。
也可以参考Martin Fowler关于InterfaceImplementationPair这个主题的有趣文章
其他回答
我倾向于遵循Java Core/Sun建立的伪约定,例如在Collections类中:
List -“概念性”对象的接口 数组列表接口的具体实现 接口的具体实现 AbstractList——抽象的“部分”实现,以帮助自定义实现
我曾经在AWT事件/监听器/适配器范例之后做同样的事情来建模我的事件类。
TruckClass听起来像是Truck的一个类,我认为推荐的解决方案是添加Impl后缀。在我看来,最好的解决方案是在实现名称中包含一些信息,在特定的实现中发生了什么(就像我们有List接口和实现:ArrayList或LinkedList),但有时你只有一个实现,并且由于远程使用(例如)必须有接口,那么(如开头提到的)Impl是解决方案。
命名你的接口。卡车。不是卡车,因为它不是卡车,它是卡车。
Java中的接口是一种类型。然后你有DumpTruck, TransferTruck, WreckerTruck, CementTruck等实现了Truck。
当您使用接口代替子类时,只需将其转换为Truck即可。如List<Truck>。把I放在前面只是匈牙利风格的符号重复,它只会在代码中添加更多的东西。
所有现代Java IDE的标记接口和实现等等都离不开这个愚蠢的符号。不要叫它TruckClass,那是和IInterface一样糟糕的重述。
If it is an implementation it is a class. The only real exception to this rule, and there are always exceptions, could be something like AbstractTruck. Since only the sub-classes will ever see this and you should never cast to an Abstract class it does add some information that the class is abstract and to how it should be used. You could still come up with a better name than AbstractTruck and use BaseTruck or DefaultTruck instead since the abstract is in the definition. But since Abstract classes should never be part of any public facing interface I believe it is an acceptable exception to the rule. Making the constructors protected goes a long way to crossing this divide.
Impl后缀也是杂音。更多的同义反复。任何不是接口的东西都是实现,即使是部分实现的抽象类也是如此。你打算在每个类的每个名字上都加上那个愚蠢的Impl后缀吗?
接口是公共方法和属性必须支持的内容的契约,它也是类型信息。所有实现卡车的东西都是一种卡车类型。
看看Java标准库本身。你看到IList ArrayListImpl LinkedListImpl了吗?不,你看到的是列表和数组列表,还有LinkedList。这里有一篇关于这个问题的好文章。任何这些愚蠢的前缀/后缀命名约定都违反了DRY原则。
此外,如果您发现自己向对象添加了DTO、JDO、BEAN或其他愚蠢的重复后缀,那么它们可能属于一个包,而不是所有这些后缀。适当打包的名称空间是自文档化的,并减少了这些构思糟糕的专有命名方案中所有无用的冗余信息,大多数地方甚至在内部都没有以一致的方式坚持这些专有命名方案。
如果要使类名唯一,只能给它加上Impl的后缀,那么您需要重新考虑是否有接口。所以当你有一个接口和一个单独的实现,而不是唯一专门化的接口时,你可能在大多数情况下不需要接口。
然而,一般来说,对于可维护性、可测试性和模拟,提供接口是最佳实践。更多细节请看这个答案。
也可以参考Martin Fowler关于InterfaceImplementationPair这个主题的有趣文章
我喜欢指示接口描述的契约的接口名称,例如“可比的”或“序列化的”。像“卡车”这样的名词并不能真正描述卡车——卡车的能力是什么?
关于惯例:我曾经工作过的项目中,每个界面都以“I”开头;虽然这与Java惯例有些不同,但它使查找接口变得非常容易。除此之外,“Impl”后缀是一个合理的默认名称。
我在这里看到的回答表明,如果你只有一个实现,那么你就不需要接口。这违背了依赖注入/控制反转原则(不要给我们打电话,我们会给你打电话!)。
So yes, there are situations in which you wish to simplify your code and make it easily testable by relying on injected interface implementations (which may also be proxied - your code doesn't know!). Even if you only have two implementations - one a Mock for testing, and one that gets injected into the actual production code - this doesn't make having an interface superfluous. A well documented interface establishes a contract, which can also be maintained by a strict mock implementation for testing.
事实上,您可以建立测试,让模拟实现最严格的接口契约(为不应该为空的参数抛出异常,等等)并在测试中捕获错误,在生产代码中使用更有效的实现(不检查不应该为空的参数是否为空,因为模拟在测试中抛出异常,并且由于在这些测试后修复了代码,您知道参数不为空)。
依赖注入/IOC对于新手来说很难理解,但是一旦你理解了它的潜力,你就会想要在任何地方都使用它,你会发现自己一直在做接口——即使只有一个(实际的生产)实现。
对于这个实现(您可以推断,并且您是正确的,我认为用于测试的模拟应该称为Mock(InterfaceName)),我更喜欢使用Default(InterfaceName)这个名称。如果出现更具体的实现,则可以适当地命名它。这也避免了我特别不喜欢的Impl后缀(如果它不是抽象类,它当然是“Impl”!)
我也更喜欢“基类(InterfaceName)”而不是“抽象(InterfaceName)”,因为在某些情况下,你希望你的基类以后成为可实例化的,但现在你被“抽象(InterfaceName)”这个名字卡住了,这迫使你重命名类,可能会造成一些小混乱-但如果它总是Base(InterfaceName),删除抽象修饰符不会改变类是什么。