接口实现类的前缀与后缀最佳实践
Contents
最近我在Twitter上问了一个问题,关于如何使用一些通用的类名前缀/后缀来搭配一个接口,看看是否有最佳实践。本篇文章是基于Java的,其他语言有不同的编码 “风格”,自然会产生不同的命名模式。
通用的Java前缀
一个接口拥有一个或多个实现的设计模式并不总是被大家看好。然而,在某些情况下,它却可能是正确的选择。我的日常工作OpenGamma平台就是其中之一。
在OpenGamma,我们正在构建一个平台,该平台将由不同公司的不同团队共同实现。这些实现通常已经存在,同时并不总是在我们的控制范围内。因此,平台对集成必须给予最低限度的设计惩罚。这显然应该使用一个接口,因为一个抽象类会施加更多的限制。
在OpenGamma内部,还必须提供某些实现接口的标准类。这可能是为了示例说明,也或者是堆栈中不同部分的其他功能。如何给这些实现标准接口的类命名,正是我在Twitter上开始对话的原因。
基于Twitter上的想法,一些其他讨论和我自己的想法,以下即所得的最佳实践:
Name | Represent |
---|---|
Foo | 这个接口最终定义的概念,所以它应该有一个最好的名字。 |
AbstractFoo | 一个抽象的实现,旨在作为一个类的层次结构的基础。 |
BaseFoo | 一个旨在作为类的层次结构的基础的实现,如果有必要,基类可以单独使用。 |
DefaultFoo | 一个 “默认 “的实现,它适用于大多数典型的用例。 |
SimpleFoo | 一个 “简单 “的实现,没有其他的功能,可以作为一个例子或作为一个模拟。一个简单的POJO就是一个很好的 “简单 “实现。 |
{Descriptive}Foo | 其他实现应该描述它们的独特之处。 |
请注意,这些 “最佳实践 “中部分可以相互结合起来。例如,一个Foo接口可能会有一个BaseFoo实现,旨在以DefaultFoo作为标准和最常用的子类。
一些其他建议的补充:
Name | Represent |
---|---|
BasicFoo | 这似乎在语义上等同于SimpleFoo,更多是个人使用偏好问题。 |
interface IFoo, class Foo | 这个命名惯例在一些地方看到,但一般不认为是好的Java风格。 |
FooImpl | 这种命名约定有一些支持者,但一般来说显得很笨拙。 |
StandardFoo | 类似于DefaultFoo,但使用较少。 |
GenericFoo | 我自己从来没有见过这个。 |
关于FooImpl还有两个想法。首先,它在自动完成(Foo ctrl+空格)中确实能很好地分组。对于方法名,我认为这很有用,但作为接口实现类并不能说服我。其次,有人建议FooImpl应该用于IoC依赖。在我看来,这似乎是将应用程序与 IoC 容器间接绑定,这并不是我喜欢的。
通用的Java后缀
在Java中,还有很多其他通用的命名模式。这些命名模式的目的是为了提高整个代码库的可读性。这与其他编码标准,如 “无制表符 “或 “行末加括号 “在概念上非常相似。这也是我的信念的一部分,在编写长寿命代码时,我们要尽最大努力帮助那些未来将阅读、使用和维护代码的人。
所以,这里补充一些最佳实践:
Name | Represent |
---|---|
Foo | 基本命名的概念应该总是有最好的名字(在本文中,它可以是一个类或接口)。 |
FooUtils | 支持使用Foo的一组实用程序。这在接口中特别常见,但不必局限于接口。在某些情况下,特别是在一个层次结构或一组类中,将常见的实用程序分离出来,只在主类上留下静态工厂方法是有意义的。我想说的是,早该有一个Javadoc注解来标记一个方法为工厂了。 |
FooBuilder | 构建器模式的一个实现,用于流畅地创建一个对象。这对于大型、复杂的对象特别有用,尤其是当最终结果是不可改变的时候。遗憾的是在Java中,一个构建器要写好是相当费劲的。 |
FooManager | 比起FooFactory,我更喜欢manager,因为我通常发现一个工厂不仅仅是创建,例如注册一个查找。然而,我倾向于避免使用显式的管理器/工厂。对于类来说,我更倾向于将管理器/工厂看作是类本身的静态方法,所以这最常被用于接口。然而,我倾向于发现我的大多数接口要么需要用户选择具体的类,要么由IoC注入。 |
DelegatingFoo | 作为一个抽象的基础存在的类,用来封装一个Foo,并通过授权添加一些行为。大多数情况下,我想说,不值得创建装饰抽象基类,而只拥有具体版本,因为它使每个类单独理解起来更简单。 |
FooProxy | 作为懒加载策略的一部分,代表完整数据集的类。我相信这有时会被用于委托的情况,但我觉得这很混乱。 |
Fooable | 这将用于一个接口,其中的实现在某种程度上与Foo相关。一个经典例子是Identifier和Identifiable。在这种情况下,-able后缀意味着实现类 “可以被识别”。在代码中,这通常意味着一个单一的getFoo()或toFoo()方法。 |
请注意,我并没有涵盖每一个前缀/后缀–还有很多其他的命名模式。有时计算机名称列表或词库是有用的。
一些其他建议的补充是:
Name | Represent |
---|---|
FooUtil | 我发现FooUtils是一个更好的名字。 |
Foos | 我使用FooUtils,因为我会把复数后缀看作是JDK的风格,就像Collections一样。 |
FooFactory | 如上所述,我发现当我确实需要一个单独的工厂时,它通常更像是一个FooManager,而不仅仅是一个工厂。 |
ForwardingFoo | 是DelegatingFoo的另一种选择,主要是Google Guava使用的。至于选择哪种,更多是个人使用偏好问题,但要保持一致。 |
DecoratingFoo | DelegatingFoo的另一个替代方案。 |
需要注意的是,大多数时候,类名应该表达出它们的独特之处。然而,有时使用命名惯例会更有益处,因为它有助于系统的学习。
总结
在类的命名或编码标准方面一般不是必须要遵守的。但是,至少应该在同一个项目中建立一个共同的标准。
欢迎大家发表不同意见。
本文翻译自 Implementations of interfaces - prefixes and suffixes and More Java prefixs and suffixes
Author Trollshuo
LastMod 2020-12-30