Именование интерфейса в Java
Большинство языков OO префикс их имени интерфейса с капиталом I, почему Java не делает этого? В чем заключалась причина не следовать этой конвенции?
Чтобы продемонстрировать, что я имею в виду, если бы я хотел иметь пользовательский интерфейс и пользовательскую реализацию, у меня было бы два варианта в Java:
- Класс = Пользователь, Интерфейс = UserInterface
- Class = UserImpl, Интерфейс = Пользователь
Где на большинстве языков:
- Что такое идеальное соглашение об именах переменных для переменных цикла?
- Использование символов подчеркивания в переменных Java и именах методов
- Руководство по присвоению имен в поле C #?
- Соглашение об именах - подчеркивание в переменных C ++ и C #
- Какую страtagsю вы используете для именования пакетов в проектах Java и почему?
Класс = Пользователь, Интерфейс = IUser
Теперь вы можете утверждать, что вы всегда можете выбрать наиболее описательное имя для пользовательской реализации, и проблема исчезнет, но Java, продвигающий подход POJO к вещам, и большинство контейнеров МОК широко используют DynamicProxies. Эти две вещи означают, что у вас будет много интерфейсов с одной реализацией POJO.
Итак, я думаю, мой вопрос сводится к следующему: «Стоит ли следовать более широкому соглашению об именовании интерфейсов, особенно в свете того, где, по-видимому, работают Java-платформы?»
- Существуют ли лучшие методы для организации пакетов (Java)?
- Соглашения об именах баз данных, таблицах и столбцах?
- Соглашение об именах интерфейсов Java / Реализация
- Как назвать исходные файлы C # для общих classов
- Венгерская нотация в C #
- Соглашение об именах classов CSS
- Соглашение об именах в c #
- Как переопределить соглашения об именах rails?
Я предпочитаю не использовать префикс на интерфейсах:
-
Префикс повреждает читаемость.
-
Использование интерфейсов в клиентах является стандартным лучшим способом программирования, поэтому имена интерфейсов должны быть максимально короткими и приятными. Реализация 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.
-
Часть объектно-ориентированного подхода заключается в том, что вам не нужно знать, использует ли клиент интерфейс или class реализации. Таким образом, даже List является интерфейсом, а String является фактическим classом, метод может быть передан им обоим – не имеет смысла визуально различать интерфейсы.
-
В общем, мы фактически предпочтем использование интерфейсов в клиентском коде (например, List List to ArrayList). Поэтому нет смысла делать интерфейсы отличными как исключения.
-
Соглашение об именах 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?
Если у вас есть соглашение об именовании магазина, не зависящее от языка, используйте его. Если нет, перейдите к соглашению об именах языков.