Именование интерфейса в Java

Большинство языков OO префикс их имени интерфейса с капиталом I, почему Java не делает этого? В чем заключалась причина не следовать этой конвенции?

Чтобы продемонстрировать, что я имею в виду, если бы я хотел иметь пользовательский интерфейс и пользовательскую реализацию, у меня было бы два варианта в Java:

  1. Класс = Пользователь, Интерфейс = UserInterface
  2. Class = UserImpl, Интерфейс = Пользователь

Где на большинстве языков:

Класс = Пользователь, Интерфейс = IUser

Теперь вы можете утверждать, что вы всегда можете выбрать наиболее описательное имя для пользовательской реализации, и проблема исчезнет, ​​но Java, продвигающий подход POJO к вещам, и большинство контейнеров МОК широко используют DynamicProxies. Эти две вещи означают, что у вас будет много интерфейсов с одной реализацией POJO.

Итак, я думаю, мой вопрос сводится к следующему: «Стоит ли следовать более широкому соглашению об именовании интерфейсов, особенно в свете того, где, по-видимому, работают Java-платформы?»

Я предпочитаю не использовать префикс на интерфейсах:

  • Префикс повреждает читаемость.

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

  • При переходе от абстрактного classа к интерфейсу соглашение о кодировании с префиксом I подразумевает переименование всех вхождений classа — нехорошо!

Есть ли разница между:

 class User implements IUser 

а также

 class UserImpl implements User 

если все, о чем мы говорим, это соглашения об именах?

Лично я предпочитаю НЕ предшествовать интерфейсу с I поскольку я хочу кодировать интерфейс, и считаю это более важным с точки зрения соглашения об именах. Если вы вызываете интерфейс IUser то каждый потребитель этого classа должен знать его IUser . Если вы вызываете class UserImpl то только class и ваш контейнер DI знают о части Impl и потребители просто знают, что они работают с User .

Опять же, времена, когда я был вынужден использовать Impl потому что лучшего имени не существует, было немного и далеко между ними, потому что реализация получает имя в соответствии с реализацией, потому что там важно, например

 class DbBasedAccountDAO implements AccountDAO class InMemoryAccountDAO implements AccountDAO 

Может быть несколько причин, по которым Java обычно не использует соглашение IUser.

  1. Часть объектно-ориентированного подхода заключается в том, что вам не нужно знать, использует ли клиент интерфейс или class реализации. Таким образом, даже List является интерфейсом, а String является фактическим classом, метод может быть передан им обоим – не имеет смысла визуально различать интерфейсы.

  2. В общем, мы фактически предпочтем использование интерфейсов в клиентском коде (например, List List to ArrayList). Поэтому нет смысла делать интерфейсы отличными как исключения.

  3. Соглашение об именах Java предпочитает более длинные имена с реальными значениями для префиксов венгерского стиля. Таким образом, код будет максимально читабельным: List представляет список, а Пользователь представляет пользователя – не IUser.

Существует также другая конвенция, используемая многими проектами с открытым исходным кодом, включая Spring.

 interface User { } class DefaultUser implements User { } class AnotherClassOfUser implements User { } 

Мне лично не нравится префикс «I» по той простой причине, что это необязательное соглашение. Итак, если я принимаю это, то IIOPConnection означает интерфейс для IOPConnection? Что делать, если class не имеет префикса «I», тогда я знаю его не интерфейс. Ответ здесь нет, потому что соглашения не всегда соблюдаются, и их контроль будет создавать больше работы, которая сама по себе сохраняет.

Как сказал другой плакат, обычно предпочтительнее, чтобы интерфейсы определяли возможности, а не типы. Я бы старался не «реализовывать» что-то вроде «Пользователь», и поэтому «IUser» часто не является необходимым в описанном здесь способе. Я часто рассматриваю classы как существительные и интерфейсы как прилагательные:

 class Number implements Comparable{...} class MyThread implements Runnable{...} class SessionData implements Serializable{....} 

Иногда Adjective не имеет смысла, но я все же обычно использовал интерфейсы для моделирования поведения, действий, возможностей, свойств и т. Д., А не типов.

Кроме того, если вы действительно собираетесь сделать только одного пользователя и назвать его User, то в чем смысл иметь интерфейс IUser? И если у вас будет несколько разных типов пользователей, которым необходимо реализовать общий интерфейс, что добавляет «I» к интерфейсу, вы можете выбрать имена реализаций?

Я думаю, что более реалистичным примером могло бы быть то, что некоторые типы пользователей должны иметь возможность входа в конкретный API. Мы могли бы определить интерфейс входа, а затем иметь родительский class «Пользователь» с SuperUser, DefaultUser, AdminUser, AdministrativeContact и т. Д. Suclasses, некоторые из которых будут или не будут использовать интерфейс Login (Loginable?) По мере необходимости.

Боб Ли сказал однажды в презентации:

В чем смысл интерфейса, если у вас есть только одна реализация.

поэтому вы начинаете с одной реализации, т.е. без интерфейса. позже вы решите, ну, здесь нужен интерфейс, поэтому вы конвертируете свой class в интерфейс.

то это становится очевидным: ваш первоначальный class называется User. ваш интерфейс теперь называется User. возможно, у вас есть UserProdImpl и UserTestImpl. если вы хорошо разработали приложение, каждый class (кроме тех, которые создают экземпляр пользователя) не изменится и не заметит, что им вдруг передается интерфейс.

так что становится понятно -> Пользовательский интерфейс UserImpl.

В C # это

 public class AdminForumUser : UserBase, IUser 

Java сказал бы

 public class AdminForumUser extends User implements ForumUserInterface 

Из-за этого, я не думаю, что соглашения почти так же важны в Java для интерфейсов, так как существует явное различие между наследованием и реализацией интерфейса. Я бы сказал, просто выберите любое соглашение об именах, которое вы хотели бы, до тех пор, пока вы являетесь последователем и используете что-то, чтобы показать людям, что это интерфейсы. За несколько лет не удалось создать java, но все интерфейсы были бы в их собственном каталоге, и это было соглашение. Никогда не было никаких проблем с этим.

По моему опыту, соглашение «I» применяется к интерфейсам, которые предназначены для предоставления контракта classу, особенно если сам интерфейс не является абстрактным понятием classа.

Например, в вашем случае я бы ожидал увидеть IUser если единственным пользователем, которого вы когда-либо хотели, является User . Если вы планируете использовать разные типы пользователей – NoviceUser , ExpertUser и т. Д. – я бы ожидал увидеть User интерфейс (и, возможно, class AbstractUser который реализует некоторые общие функции, такие как get/setName() ).

Я бы также ожидал, что интерфейсы, которые определяют возможности – Comparable , Iterable и т. Д. – будут называться так, а не как IComparable или IIterable .

Следуя хорошим принципам OO, ваш код должен (насколько это практично / возможно) зависеть от абстракций, а не от конкретных classов. Например, обычно лучше написать такой метод:

 public void doSomething(Collection someStuff) { ... } 

чем это:

 public void doSomething(Vector someStuff) { ... } 

Если следовать этой идее, я утверждаю, что ваш код будет более читабельным, если вы укажете имена интерфейсов, например «Пользователь» и «БанкАккаунт» (например), а не «IUser», «UserInterface» или другие варианты.

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

Если вы это сделаете, то «уродливые» конкретные имена classов, такие как «UserImpl», должны быть безопасно скрыты от остальной части кода, которые могут весело продолжать использовать «приятные» имена интерфейсов.

= v = Префикс «I» также используется в каркасе Wicket, где я быстро привык к нему. В общем, я приветствую любое соглашение, которое сокращает громоздкие classы Java. Однако все дело в том, что все в алфавитном порядке под «I» в каталогах и в Джавадоке.

Практика кавитного кодирования похожа на Swing, поскольку многие экземпляры управления / виджета создаются как анонимные внутренние classы с объявлениями встроенных методов. Раздражающе, он отличается на 180 ° от Swing тем, что Swing использует префикс («J») для classов реализации.

Суффикс «Impl» является аббревиатурой mangly и не интернационализируется хорошо. Если бы мы по крайней мере поехали с «Импом», это было бы немного (и короче). «Impl» используется для IOC, особенно Spring, поэтому мы сейчас застряли с ним. Тем не менее, он получает немного шизо, следуя 3 различным соглашениям в трех разных частях одной кодовой базы.

Является ли это более широким соглашением об именах в каком-либо реальном смысле? Я больше на стороне C ++, а не на Java и потомках. Сколько языковых сообществ использует конвенцию I?

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

  • Какое соглашение об именах пакетов вы используете для личных / хобби проектов на Java?
  • Должен ли быть объявлен «статический конечный регистратор» в ВЕРХНЕЙ ЧАСТИ?
  • Сингулярные или множественные имена controllerов и помощников в Rails
  • Соглашение о назначении Java с помощью сокращений
  • Каковы соглашения об именах в C #?
  • Interesting Posts

    Приложение IIS с использованием идентификатора пула приложений теряет основной токен?

    Является ли IE 11 последним и доступен для Windows 8 Pro x64?

    Метод Razor ViewEngine HTML.Checkbox создает скрытый ввод. Зачем?

    Как узнать, какая программа создает файл / папку на моем диске C:?

    Ограничьте каждого пользователя только своей собственной домашней папкой

    Почему Stream не имеет метода toList ()?

    Как внедрить AuthenticationManager с использованием конфигурации Java в пользовательский фильтр

    Проблема с отображением клавиатуры Snow Leopard

    Использование списков внутри столбцов data.table

    Скопируйте файлы с определенным расширением в папку

    Что такое «жизненный цикл страницы» ASP.NET WebForm?

    Как использовать беспроводное и проводное соединение одновременно в Windows 7?

    Использование сборки с ассоциацией has_one в рельсах

    производительность целых чисел без знака и знака

    Создание UIImage в форме круга

    Давайте будем гением компьютера.