Подтвердить что ты не робот

Соглашения об именовании интерфейса Java

Я работаю над веб-приложением Java, которое использует Spring для инъекций зависимостей и JMock для издевательства этих зависимостей в наших модульных тестах.

В настоящее время наша команда в какой-то момент имеет несколько разных мнений относительно того, как назвать определенные интерфейсы, которые мы используем. У нас нет проблем с именами интерфейсов в нашем домене, которые имеют множество реализаций, это просто. Однако, когда дело доходит до интерфейсов, для которых у нас есть только одна реализация и предполагается только одна реализация в будущем, мы попали в заблуждение.

Причина, по которой у нас есть такие интерфейсы, - это просто для насмешек, например, у нас есть сервисы и репозитории, которые мы изматываем в наших модульных тестах, и эти службы будут называться "DocumentMappingService" или для репозиториев "EmployeeRepository". На данный момент некоторые из парней просто префикс связанного имени интерфейса с "I", то есть "IDocumentMappingService" и "IEmployeeRepository". Другие называют интерфейс, как я уже выше, а затем добавьте "Impl" после имени интерфейса для класса реализации.

Третья "фракция" считает, что обе эти варианты бедны. Глядя на литературу, такую ​​как известное "Растущее объектно-ориентированное программное обеспечение, руководствуясь тестами", можно было бы предположить, что оба из указанных выше вариантов являются плохими и что имя интерфейса должно четко определять контракт и имя классов реализации должен четко указывать, как этот контракт был реализован. Мы обнаружили, что это довольно сложно сделать в случае, о котором я упомянул выше.

Я надеялся, что у кого-то там была аналогичная проблема раньше, и есть некоторые предложения, которые этот вариант является лучшим и почему. Кроме того, если вы считаете, что параметры "I" и "Impl" являются плохими, пожалуйста, предложите конкретное альтернативное соглашение.

4b9b3361

Ответ 1

Здесь нет "одного" правильного ответа. Именование очень субъективно, но самое главное, что он должен быть согласованным на всей базе кода. Я просто хотел бы добавить (к @fge answer) еще несколько вариантов для вас:

  • Создание интерфейсов более общий.

    EmployeeRepository implements Repository
    DocumentMappingService implements MappingService
    
  • Вызов единой реализации "по умолчанию".

    DefaultEmployeeRepository implements EmployeeRepository
    DefaultDocumentMappingService implements DocumentMappingService
    
  • Вызов базовых реализаций (если они иногда расширены) как "поддержка".

    EmployeeRepositorySupport implements EmployeeRepository
    DocumentMappingServiceSupport implements DocumentMappingService
    

Я часто встречаюсь с этими соглашениями об именах при использовании Spring Framework.


Изменить: В ответ на комментарий пользователя nyxz о соглашении -Base или Base- .

Как я уже говорил, именование является субъективным, и нет ничего плохого в использовании номенклатуры Base как таковой. Но, лично, я не предпочитаю его использовать. Вот почему:

  • Если ваши реализации в основном будут использоваться напрямую, тогда код, создающий экземпляр классов, оставляет впечатление нарушения иерархии ООП. Возможно, что определенный производный класс был создан.

  • Если ваши реализации будут в основном расширены, тогда слово Base становится избыточным. Вы расширяетесь от него, поэтому, конечно, это базовый класс. Duh!

Точка 2nd в основном применяется к периферийным классам вашего проекта. Точки расширения, которые вы предоставляете, когда публикуете фреймворк или библиотеку, которые будут использоваться и расширены в других проектах.

С другой стороны, хорошим примером использования терминов Base было бы для классов, внутренних для вашей структуры, которые учитывают общую функциональность из других периферийных классов. Поскольку эти классы не должны создаваться непосредственно, они помечены abstract, что соответствует строке 1st.

Здесь иерархия Adapter из фреймворка Android в качестве примера:

  • Иерархия интерфейсов.

    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<T> extends BaseAdapter implements Filterable
    

Ответ 2

Ответ на такой вопрос может отражать только вкусы человека, который отвечает... Итак, это мои вкусы:

  • Я ненавижу начальный I. Это не приносит ничего полезного для картины. Это напоминает мне венгерскую нотацию, в которой плавающие переменные должны быть суффиктированы с помощью _f или тому подобное. Нет.
  • Суффикс Impl достаточно хорош. Но, с другой стороны, это звучит странно.

Я бы предложил два альтернативных предложения для данного интерфейса Foo:

  • создать единую реализацию, но не с суффиксом Impl; найти более "привлекательное" имя. Например, TheOnlyOneFoo;
  • создайте factory с добавленным s: Foos. Тогда экземпляр Foo будет Foos.newInstance(whatever, args).

Я предпочитаю второе решение по двум причинам:

  • он может скрыть тот факт, что реальная реализация имеет уродливое имя;
  • он может быть легко расширен, когда вы осознаете, что "нет, в конце концов, для этого существует более одной реализации": просто добавьте еще один статический метод factory; и если единственный существующий существующий метод звучит слишком общий, вы можете просто отметить его как @Deprecated.

Его можно даже использовать таким образом, чтобы все реализации Foo были локальными пакетами или даже были закрыты для factory. Но трассировка стека будет выглядеть хуже...

Нет реального решения там;)

edit: что касается насмешек:

  • Я бы порекомендовал mockito. В самом деле. Он очень прост в использовании и очень мощный.
  • Если это "классы с одной реализацией", с которыми вы имеете дело, возможно, в самой JDK есть лучшая альтернатива? Что вы хотите сделать именно так? JDK имеет скрытые сокровища...

И как последнее примечание... Вы рассматривали шаблон строителя?