Java接口命名约定

我在一个Java Web应用程序上工作,它使用Spring进行dependency injection,JMock用于在我们的unit testing中模拟这些依赖项。

目前我们的团队在某一点上,我们在如何命名我们使用的某些界面方面有一些不同的意见。 我们在域中命名具有多个实现的接口没有问题,这很简单。 但是,当谈到我们只有一个实现并且打算将来只有一个实现的接口时,我们遇到了障碍。

我们有这样的接口的原因纯粹是为了模拟,例如,我们有我们在unit testing中模拟的服务和存储库,这些服务将被命名为“DocumentMappingService”或存储库“EmployeeRepository”。 目前,一些人只是在关联的接口名称前加上“I”,即“IDocumentMappingService”和“IEmployeeRepository”。 其他人如上所述命名接口,然后在实现类的接口名称后添加“Impl”。

第三个“派系”认为这两个选项都很差。 查看众所周知的“以测试为导向的面向对象的软件”这样的文献会让人相信前面提到的两个选项都很差,并且接口名称应该明确定义合同和实现类名称应明确说明合同是如何实施的。 我们发现在上面提到的情况下这很难做到。

我希望那里的某个人之前有类似的问题并且有一些建议,哪个选项是最好的,为什么。 此外,如果您认为“I”和“Impl”选项都很差,那么请建议一个特定的替代惯例。

这里没有“一个”正确答案。 命名是非常主观的,但最重要的是它应该在整个代码库中保持一致 。 我想为你添加更多选项(@ fge的答案):

  • 使接口更通用。

     EmployeeRepository implements Repository DocumentMappingService implements MappingService 
  • 将您的单个实现调用为“默认值”

     DefaultEmployeeRepository implements EmployeeRepository DefaultDocumentMappingService implements DocumentMappingService 
  • 将您的基本实现(如果,有时会扩展)称为“支持”

     EmployeeRepositorySupport implements EmployeeRepository DocumentMappingServiceSupport implements DocumentMappingService 

在使用Spring Framework时,我经常遇到这些命名约定。


编辑:回应用户nyxz关于nyxznyxz的评论。

就像我之前说过的那样,命名是主观的,使用Base命名法也没有错。 但是,就个人而言,我不喜欢使用它。 原因如下:

  1. 如果您的实现主要是直接使用,那么实例化类的代码会留下打破OOP层次结构的印象。 也许应该实例化一个特定的派生类。

  2. 如果您的实现主要是扩展的,那么Base这个词在某种程度上会变得多余。 你正在扩展它,当然,它是一个基类。 咄!

第二点主要适用于项目中的外围类。 您在发布要在其他项目中使用和扩展的框架或库时提供的扩展点。

另一方面,使用Base术语的一个很好的用例是用于框架内部的类,它将其他外围类的常用function考虑在内。 因为,这些类不应该直接实例化,所以它们被标记为abstract ,这与第一点一致。

以下是Android框架中的Adapter层次结构示例:

  • 接口层次结构

     public interface Adapter public interface ListAdapter extends Adapter public interface SpinnerAdapter extends Adapter 
  • abstract Base类,它解决了常见的行为和接口实现。

     public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter 
  • 外围类主要是实例化但有时由Android应用程序扩展。

     public class SimpleAdapter extends BaseAdapter implements Filterable public class ArrayAdapter extends BaseAdapter implements Filterable 

这个问题的答案只能反映回答者的口味……所以这些是我的口味:

  • 我讨厌最初的I 。 它没有给图片带来任何价值。 它让我想起了匈牙利符号,其中浮点变量后缀为_f等。 没有。
  • Impl后缀足够好。 但另一方面,这听起来很奇怪。

我建议给定接口Foo两个备用提议:

  • 创建单个实现但不使用Impl后缀; 找到一个更“吸引人”的名字。 例如, TheOnlyOneFoo ;
  • 用附加的sFoos创建一个工厂。 然后,一个Foo实例将是一个Foos.newInstance(whatever, args)

我更喜欢第二种解决方案,原因有两个:

  • 它可以隐藏真实实现具有丑陋名称的事实;
  • 当你意识到有一天“不,毕竟有不止一个实现”时,它可以很容易地扩展:只需添加另一个静态工厂方法; 如果现有的唯一现有方法听起来过于通用,则可以将其标记为@Deprecated

它甚至可以以一种方式使用,以便所有Foo实现都是本地包,甚至是工厂的私有。 但堆栈痕迹看起来会更糟……

没有真正的解决方案;)

编辑:至于嘲笑:

  • 我推荐mockito。 真。 它非常易于使用,而且非常强大。
  • 如果那些是你正在处理的“一个实现类”,那么JDK本身可能有更好的选择吗? 你想要做的是什么? JDK隐藏着宝藏……

最后一点说明……你是否考虑过建造者模式?