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

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

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

  • Класс = Пользователь, Интерфейс = Пользовательский интерфейс
  • Класс = UserImpl, Интерфейс = Пользователь

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

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

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

Итак, я думаю, мой вопрос сводится к следующему: "Стоит ли следовать более широкому соглашению об именовании интерфейсов, особенно в свете того, что Java Frameworks, кажется, заголовок?"

Ответ 1

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

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

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

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

Ответ 2

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

class User implements IUser

и

class UserImpl implements User

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

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

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

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

Ответ 3

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

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

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

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

Ответ 4

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

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

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

Ответ 5

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

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

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

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

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

Ответ 6

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

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

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

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

чтобы оно стало понятным → Пользовательский интерфейс пользователя UserImpl.

Ответ 7

В С# это

public class AdminForumUser : UserBase, IUser

Java скажет

public class AdminForumUser extends User implements ForumUserInterface

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

Ответ 8

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

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

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

Ответ 9

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

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

чем это:

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

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

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

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

Ответ 10

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

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

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

Ответ 11

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

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