Соглашение о присвоении имен Интерфейсов/Реализации Java [дубликат]

315
задан Joshua Taylor 11 March 2016 в 10:13
поделиться

9 ответов

Назовите свой интерфейс , что это такое. Грузовик . Не ITruck , потому что это не ITruck , это Truck .

Интерфейс в Java - это Тип . Затем у вас есть DumpTruck , TransferTruck , WreckerTruck , CementTruck и т. Д., Которые используют Truck .

Когда вы используете интерфейс вместо подкласса, вы просто применяете его к Truck . Как в List .Ввод I впереди - это просто венгерский стиль нотация тавтология , которая не добавляет ничего, кроме дополнительных элементов для ввода в ваш код.

Все современные Java IDE помечают интерфейсы и реализации, и многое другое без этих глупых обозначений. Не называйте это TruckClass , это тавтология так же плохо, как тавтология IIинтерфейса .

Если это реализация, то это класс. Единственным реальным исключением из этого правила, и всегда есть исключения, может быть что-то вроде AbstractTruck . Поскольку это когда-либо увидят только подклассы, и вы никогда не должны приводить к классу Abstract , он добавляет некоторую информацию о том, что класс является абстрактным и как его следует использовать. Вы все равно можете придумать имя получше, чем AbstractTruck , и использовать вместо него BaseTruck или DefaultTruck , поскольку в определении содержится аннотация . Но поскольку Абстрактные классы никогда не должны быть частью какого-либо общедоступного интерфейса, я считаю, что это приемлемое исключение из правила. Обеспечение защиты конструкторов имеет большое значение для преодоления этого разрыва.

И суффикс Impl - это еще больше шума. Больше тавтологии. Все, что не является интерфейсом, является реализацией, даже абстрактные классы, которые являются частичными реализациями.Вы собираетесь добавить этот глупый суффикс Impl к каждому имени каждого Class ?

Интерфейс - это договор о том, что должны поддерживать общедоступные методы и свойства, а также информация о типе . Все, что оснащено Грузовиком , представляет собой Тип из Грузовик .

Посмотрите на саму стандартную библиотеку Java. Вы видите IList , ArrayListImpl , LinkedListImpl ? Нет, вы видите List и ArrayList и LinkedList . Вот хорошая статья об этом точном вопросе. Любые из этих глупых соглашений об именах префиксов / суффиксов также нарушают принцип DRY .

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

Если все, что вы можете придумать, чтобы сделать свое имя Class уникальным, - это добавить к нему суффикс Impl , то вам нужно вообще переосмыслить наличие интерфейса . . Итак, когда у вас есть ситуация, когда у вас есть Интерфейс и единственная Реализация , которая не является однозначно специализированной по сравнению с Интерфейсом , вам, вероятно, не понадобится Интерфейс .

860
ответ дан 23 November 2019 в 01:06
поделиться

Мне нравятся названия интерфейсов, которые указывают, какой контракт описывает интерфейс, например "Сравнимый" или "Сериализуемый". Существительные типа "Truck" не описывают суть грузовика - каковы способности грузовика?

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

22
ответ дан 23 November 2019 в 01:06
поделиться

Имя интерфейса должно описывать абстрактную концепцию, которую представляет интерфейс. Любой класс реализации должен иметь какие-то особые черты, которые можно использовать, чтобы дать ему более конкретное имя.

Если существует только один класс реализации и вы не можете придумать ничего, что делало бы его конкретным (подразумевается, что вы хотите назвать его -Impl ), то, похоже, нет никаких оснований для того, чтобы иметь интерфейс вообще.

62
ответ дан 23 November 2019 в 01:06
поделиться

Некоторым это не нравится, и это больше похоже на соглашение .NET, чем на Java, но вы можете называть свои интерфейсы с префиксом с заглавной буквы I, например:

IProductRepository - interface
ProductRepository, SqlProductRepository, etc. - implementations

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

Я бы не стал называть класс реализации суффиксом «Class». Это может привести к путанице, потому что вы действительно можете работать с объектами «класса» (т.е. типа) в своем коде, но в вашем случае вы не работаете с объектом класса, вы просто работаете с обычным старым объектом. .

11
ответ дан 23 November 2019 в 01:06
поделиться

Стандартная конвенция C#, которая достаточно хорошо работает и в Java, заключается в том, чтобы префиксировать все интерфейсы с I - таким образом, ваш интерфейс обработчика файлов будет IFileHandler, а ваш интерфейс грузовика будет ITruck. Это последовательно, и позволяет легко отличать интерфейсы от классов.

30
ответ дан 23 November 2019 в 01:06
поделиться

Я склонен следовать псевдоконвенциям, установленным в Java Core/Sun, напр. в классах Collections:

  • List - интерфейс для "концептуального" объекта
  • ArrayList - конкретная реализация интерфейса
  • LinkedList - конкретная реализация интерфейса
  • AbstractList - абстрактная "частичная" реализация для помощи пользовательским реализациям

Я делал то же самое, моделируя свои классы событий в соответствии с парадигмой AWT Event/Listener/Adapter.

31
ответ дан 23 November 2019 в 01:06
поделиться

TruckClass звучит так, как будто это класс Truck , я думаю, что рекомендуемое решение - добавить суффикс Impl . На мой взгляд, лучшее решение - содержать в названии реализации некоторую информацию о том, что происходит в этой конкретной реализации (как у нас с интерфейсом List и реализациями: ArrayList или LinkedList ), но иногда у вас есть только одна реализация и вам нужен интерфейс из-за удаленного использования (например), тогда (как упоминалось в начале) Impl является решением.

0
ответ дан 23 November 2019 в 01:06
поделиться

Я использую оба соглашения:

Если интерфейс является конкретным экземпляром хорошо известного паттерна (например, Service, DAO), то ему может не понадобиться "I" (например, UserService, AuditService, UserDao), все они прекрасно работают без "I", потому что постфикс определяет мета-шаблон.

Но если у вас есть что-то одноразовое или двухразовое (обычно для шаблона обратного вызова), то это поможет отличить его от класса (например, IAsynchCallbackHandler, IUpdateListener, IComputeDrone). Это интерфейсы специального назначения, предназначенные для внутреннего использования, иногда IInterface обращает внимание на то, что операнд на самом деле является интерфейсом, так что с первого взгляда это сразу понятно.

В других случаях вы можете использовать I, чтобы избежать столкновения с другими широко известными конкретными классами (ISubject, IPrincipal vs Subject или Principal).

1
ответ дан 23 November 2019 в 01:06
поделиться

Я видел здесь ответы, которые предполагают, что если у вас есть только одна реализация, вам не нужен интерфейс. Это противоречит принципу внедрения / инверсии управления зависимостями (не звоните нам, мы вам позвоним!).

Итак, да, есть ситуации, в которых вы хотите упростить свой код и сделать его легко тестируемым, полагаясь на внедренные реализации интерфейса (которые также могут быть проксированы - ваш код не знает!). Даже если у вас есть только две реализации - одна Mock для тестирования, а другая внедряется в реальный производственный код, это не делает наличие интерфейса излишним. Хорошо документированный интерфейс устанавливает контракт, который также может поддерживаться строгой фиктивной реализацией для тестирования.

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

Внедрение зависимостей / IOC может быть трудным для понимания новичку, но как только вы поймете его потенциал, вы захотите использовать его повсюду, и вы обнаружите, что постоянно создаете интерфейсы - даже если это будет только быть одной (реальной производственной) реализацией.

Для этой одной реализации (вы можете сделать вывод, и будете правы, что я считаю, что макеты для тестирования должны называться Mock (InterfaceName)), я предпочитаю имя Default (InterfaceName). Если появится более конкретная реализация, ее можно будет назвать соответствующим образом. Это также позволяет избежать суффикса Impl, который мне особенно не нравится (если это не абстрактный класс, конечно, это "impl"!).

Я также предпочитаю «Base (InterfaceName)», а не «Abstract (InterfaceName)», потому что в некоторых ситуациях вы хотите, чтобы ваш базовый класс стал экземпляром позже, но теперь вы застряли с именем «Abstract ( InterfaceName) ", и это вынуждает вас переименовать класс, что может вызвать небольшую путаницу - но если он всегда был Base (InterfaceName), удаление модификатора abstract не меняет того, каким был класс.

100
ответ дан 23 November 2019 в 01:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: