Java 接口命名约定 [已关闭]

2022-09-01 15:42:11

我开发一个Java Web应用程序,它使用Spring进行依赖注入,并使用JMock在我们的单元测试中模拟这些依赖关系。

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

我们拥有此类接口的原因纯粹是为了模拟,例如,我们在单元测试中模拟了服务和存储库,这些服务将被命名为“DocumentMappingService”或存储库“EmployeeRepository”。目前,有些人只是在相关的接口名称前面加上“I”,即“IDocumentMappingService”和“IEmployeeRepository”。其他人像我上面所说的那样命名接口,然后在实现类的接口名称后附加一个“Impl”。

第三个“派系”认为这两个选项都很差。查看诸如众所周知的“在测试的指导下发展面向对象的软件”之类的文献,人们会认为前面提到的两个选项都很差,并且接口名称应该清楚地定义契约,实现类名称应该清楚地指定该契约是如何实现的。但是,在我上面提到的情况下,我们发现这很难做到。

我希望有人以前遇到过类似的问题,并有一些建议,即哪种选择是最好的以及为什么。另外,如果您认为“I”和“Impl”选项都很差,那么请建议一个特定的替代约定。


答案 1

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

  • 使接口更加通用。

    EmployeeRepository implements Repository
    DocumentMappingService implements MappingService
    
  • 将单个实现称为“默认值”。

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

    EmployeeRepositorySupport implements EmployeeRepository
    DocumentMappingServiceSupport implements DocumentMappingService
    

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


编辑:回应用户对或约定的评论。nyxz-BaseBase-

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

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

  2. 如果你的实现大部分是从扩展而来的,那么这个词在某种程度上就变得多余了。你正在从它扩展,所以,当然,它是一个基类。嗯!Base

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

另一方面,使用术语的一个很好的用例是用于框架内部的类,这些类将公共功能与其他外围类区分开来。由于这些类不应该直接实例化,因此它们被标记为 ,这与第一点一致。Baseabstract

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

  • 接口层次结构。

    public interface Adapter
    public interface ListAdapter extends Adapter
    public interface SpinnerAdapter extends Adapter
    
  • 分解常见行为和接口实现的类。abstractBase

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

    public class SimpleAdapter extends BaseAdapter implements Filterable
    public class ArrayAdapter<T> extends BaseAdapter implements Filterable
    

答案 2

对这样一个问题的答案只能反映回答的人的品味......所以这些是我的口味:

  • 我讨厌首字母.它没有给图片带来任何价值。这让我想起了匈牙利符号,其中浮点变量的后缀或类似。不。I_f
  • 后缀已经足够好了。但另一方面,这听起来很奇怪。Impl

我建议为给定的接口提出两个替代建议:Foo

  • 创建单个实现,但不带后缀;找到一个更“吸引人”的名字。例如ImplTheOnlyOneFoo;
  • 创建一个附加了 : 的工厂。然后,实例将是 .sFoosFooFoos.newInstance(whatever, args)

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

  • 它可以掩盖这样一个事实,即真正的实现有一个丑陋的名字;
  • 当你有一天意识到“不,毕竟,有多个实现”时,它可以很容易地扩展:只需添加另一个静态工厂方法;如果存在的唯一现有方法听起来太通用,则可以将其标记为 .@Deprecated

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

没有真正的解决方案;)

编辑:至于嘲笑:

  • 我会推荐嘲笑。真。它非常易于使用,并且非常强大。
  • 如果这些是您正在处理的“单实现类”,那么JDK本身也许有更好的选择?您到底想做什么?JDK有隐藏的宝藏...

最后要注意...您是否考虑过生成器模式?