Именование интерфейса в Java [закрыто]

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

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

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

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

Class = User, Interface = IUser

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

Так, я думаю, мой вопрос сводится к: "стоит ли следовать более широкому соглашению об именовании интерфейса, особенно в свете того, куда, похоже, направляются Java-фреймворки?"

11 ответов


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

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

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

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


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

class User implements IUser

и

class UserImpl implements User

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

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

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

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

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

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

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

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


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

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

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


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

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

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

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

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


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

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

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

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

таким образом, становится ясно - > пользовательский интерфейс реализации UserImpl.


В C# это

public class AdminForumUser : UserBase, IUser

Java сказал бы

public class AdminForumUser extends User implements ForumUserInterface

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


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

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

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


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

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

чем этот:

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

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

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

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


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

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

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


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

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