Именование интерфейса в Java [закрыто]
большинство языков OO префикс их имена интерфейса с заглавной буквы I, почему Java не делает этого? Чем объясняется несоблюдение этой конвенции?
чтобы продемонстрировать, что я имею в виду, если бы я хотел иметь пользовательский интерфейс и пользовательскую реализацию, у меня было бы два варианта на Java:
- Класс = Пользователь, Интерфейс = UserInterface
- 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.
часть объектно-ориентированного подхода заключается в том, что вам не нужно знать, использует ли клиент интерфейс или класс реализации. Таким образом, даже List - это интерфейс, а String-фактический класс, метод может быть передан им обоим-нет смысла визуально различать интерфейсы.
В общем, мы на самом деле предпочитают использование интерфейсов в клиентском коде (например, список предпочтительнее ArrayList). Поэтому нет смысла выделять интерфейсы как исключения.
соглашение об именах 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?
Если у вас есть независимое от языка стандартное соглашение об именах магазина, используйте его. Если нет, перейдите к соглашению об именовании языков.