Это плохая практика иметь интерфейс для определения констант?


40

Я пишу набор тестовых классов junit на Java. Есть несколько констант, например, строки, которые мне понадобятся в разных тестовых классах. Я думаю об интерфейсе, который определяет их, и каждый тестовый класс будет реализовывать его.

Я вижу здесь следующие преимущества:

  • легкий доступ к константам: MY_CONSTANTвместоThatClass.MY_CONSTANT
  • каждая константа определена только один раз

Этот подход - хорошая или плохая практика? Я чувствую, что немного злоупотребляю концепцией интерфейсов.

Вы можете ответить в основном об интерфейсах / константах, но также и о модульных тестах, если есть что-то особенное в этом.


Ответ на вопрос «Это плохая практика - иметь интерфейс, определяющий X?», Поскольку X является чем-то, что не является «сигнатурой метода», почти всегда наверняка «Да».
Т. Сар - Восстановить Монику

Ответы:


79

Джошуа Блох советует против этого в своей книге « Эффективная Java» :

То, что класс использует некоторые константы внутри, является деталью реализации. Реализация постоянного интерфейса вызывает утечку этой детали реализации в экспортируемый API классов. Для пользователей класса не имеет значения, что класс реализует постоянный интерфейс. На самом деле, это может даже запутать их. Хуже того, он представляет собой обязательство: если в будущем выпуске класс будет изменен так, что ему больше не нужно будет использовать константы, он все равно должен реализовать интерфейс для обеспечения двоичной совместимости.

Вы можете получить тот же эффект с обычным классом, который определяет константы, а затем использовать import static com.example.Constants.*;


13

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

НЕКОТОРЫЕ константы являются деталями реализации. ИНОГДА они не. Как обычно, инженер должен использовать свой мозг, чтобы решить, что делать, а не полагаться на развернутый шаблон или практику.


7

Я не думаю, что хорошо иметь интерфейсы только для констант.

Но если интерфейс, который определяет поведение (методы, реализующие классы должны реализовывать), имеет константы, это нормально. Если он «пропускает некоторые детали разработчика» в API, это потому, что так оно и должно быть. Они также сообщают, что разработчик реализует методы foo и bar.

Взять, к примеру, интерфейс java.awt.Transparency. Он имеет константы OPAQUE, BITMASK и TRANSLUCENT, но также имеет метод getTransparency ().

Если дизайнер поместил эти константы туда, это потому, что он / она думал, что он будет достаточно стабильным, чтобы быть частью интерфейса, как getTransparency ().


2

Думаю, это точка зрения, наиболее популярная в тех местах, где дизайн по контракту преобладает.
Интерфейсы являются контрактами. Размещение констант в интерфейсах означает, что каждый класс, который соблюдает контракт, соглашается со значением / концепцией, определенной константой.


1
интерфейсы являются публичными контрактами. Постоянные ЗНАЧЕНИЯ являются частной заботой, публичный интерфейс должен максимально раскрыть их имена. Это лучше оставить абстрактному классу.
С

Примеры: javax.naming.Context, javax.ims.Session и сотни таких интерфейсов ...
CMR

2
@jwenting Кроме того, может ли публичный интерфейс "at most expose their names", не раскрывая значения?
CMR

Я думаю, это зависит от языка программирования. В случае с Java нет.
jwenting

2

Компания, в которой я работал, интенсивно использовала импортированные интерфейсом 1 константы. Я не чувствую никакого вреда от этого.

Вопрос, который вы должны задать себе: насколько важно для вас пространство имен? В случае констант, это действительно все, что действует класс. Если у вас есть тысячи констант, вы можете не хотеть, чтобы все эти константы были всегда доступны.

Крутая вещь об интерфейсах - это то, что она дает вам преимущество работы в любом случае - вводите все необходимые вам пространства имен или ни одного из них (и обращайтесь к ним явно, с помощью MyInterface.CONSTANT). Почти то же самое import static MyInterface.*, но немного более очевидно.


1: Если вы не знакомы с Java, я не имею в виду importключевое слово, я просто имею в виду привезены черезimplements MyConstantsInterface


1

Я родом из прошлого, который в основном зависит от «пути Ады» и «пути .Net». Я бы сказал нет, что, вероятно, не лучше объявлять константы в интерфейсах. Это технически не разрешено в c #.

Причина, по которой я говорю «нет», заключается в том, что интерфейс - это форма контракта, которая определяет поведение, а не состояние или структуру. Константа подразумевает какое-то состояние (примитив) или аспект состояния (составной или совокупный).

Я могу оценить стремление сделать значения по умолчанию и предопределенные значения доступными для всех, кто реализует интерфейс, но, возможно, состояние по умолчанию лучше было бы описать в абстрактном объекте или объекте значения или шаблоне, где значения по умолчанию имели бы как минимум минимальный контекст.

Для более технического руководства: download.oracle.com/javase/1.5.0/docs/guide/language/static-import.html


Добавление большего количества ссылок со ссылкой на Static Import (1,5): 1. Википедия 2. Oracle Docs ссылки @Justinc
Abhijeet

1
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Отзыв от Oracle Docs
Abhijeet

1

Нет, это не плохая практика.

Дело в том, что константы, как и любой другой артефакт, должны вводиться по правилам минимальной видимости и надлежащего уровня абстракции.

Использование синтаксиса только потому, что вы можете это настоящая проблема.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.