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

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

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

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

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

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

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

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


person Allain Lalonde    schedule 12.02.2009    source источник
comment
Где на большинстве языков? Какие языки кроме .Net?   -  person wds    schedule 12.02.2009
comment
Не все .NET; C++ — это пригодный для использования язык .NET и не имеет интерфейсов как таковых (абстрактные базовые классы могут поставляться с некоторой реализацией). Сводится ли этот вопрос к тому, почему Java не похожа на С#??   -  person David Thornley    schedule 12.02.2009
comment
Нет, вопрос основан на Java, но на самом деле это вопрос о соглашениях об именах интерфейсов и о том, почему некоторые языки предпочитают делать что-то определенным образом.   -  person Allain Lalonde    schedule 12.02.2009
comment
Разные языковые сообщества имеют разные соглашения об именах, и это было верно в течение очень долгого времени. Выяснение того, как возникли соглашения об именах, иногда является по сути фольклорным исследованием.   -  person David Thornley    schedule 12.02.2009
comment
Eclipse — существенное исключение, использующее Java с именованием в стиле IFoo. wiki.eclipse.org/Naming_Conventions   -  person David Leonard    schedule 24.01.2011
comment
Помимо .NET, Adobe Flash/Flex также использует соглашение об именах IFoo.   -  person Sam    schedule 10.03.2011
comment
До .NET интерфейсы COM обычно назывались с префиксом I, например. IНеизвестно, IStream. В C++ было принято использовать IStream* и тому подобное при взаимодействии с COM. Это похоже на естественное расширение префикса C- для классов, хотя мне кажется интересным, что .NET отказалась от префиксов классов. Delphi использовала одно и то же соглашение как для своих собственных интерфейсов, так и для использования COM-интерфейсов. Лично я не против конвенции. Вопрос ОП здесь указывает на некоторое разочарование в соглашениях об именах интерфейсов Java; Я хотел бы, чтобы стандарт был установлен.   -  person Ritchie annand    schedule 22.09.2012
comment
Если вы посмотрите на имена интерфейсов в Android SDK (в том числе и на Java), вы увидите, что они использовали соглашение о наличии слова «Интерфейс» в конце имени интерфейса, например NetworkInterface, DialogInterface и т. д.   -  person sandalone    schedule 16.08.2013
comment
Как можно закрыть этот вопрос как неконструктивный, когда он так популярен и интересен стольким людям?   -  person inor    schedule 26.08.2014
comment
Потому что на него нет правильного ответа. Я задал его до того, как SO был столь же строг в отношении вопросов, которые он принимает.   -  person Allain Lalonde    schedule 27.08.2014
comment
Я уважаю, что вы сами находите ценность в закрытии вопроса. Однако на самом деле это вопрос, на который можно ответить, если его переформулировать. Кроме того, даже несмотря на то, что он закрыт, его можно использовать для пометки других (возможно, лучше сформулированных) незакрытых вопросов как дубликатов. Это просто не имеет смысла. На основе библиотек Java, если бы они следовали собственному соглашению, это был бы интерфейс[yourInterfaceName]; на основании Abstract....   -  person ChiefTwoPencils    schedule 07.02.2015
comment
Лучший совет, который я нашел до сих пор в отношении соглашения об именах классов и интерфейсов, заключается в том, что имена интерфейсов всегда должны быть прилагательными (где это возможно), описывающими принудительное поведение класса (существительное)! как указано здесь - iwombat.com/standards/   -  person Neo182    schedule 25.03.2015
comment
Я использую соглашения, представленные здесь. howtodoinjava.com/java/basics/java-naming-conventions   -  person Jeffrey    schedule 19.03.2019


Ответы (11)


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

  • Префикс ухудшает читабельность.

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

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

person starblue    schedule 12.02.2009
comment
Полностью согласен. Еще одна клавиша для ввода, если вы используете автозаполнение. Множество файлов, начинающихся с буквы I. - person Kalecser; 12.02.2009
comment
Любая приличная IDE упрощает изменение кода так, как вы описываете. Кроме того, при переходе от абстрактного класса к интерфейсу я уверен, что вашим клиентам все равно потребуется перекомпилировать. - person Allain Lalonde; 13.02.2009
comment
Очень поздно, но: совсем не имеет значения, если IDE упрощает изменение имени чего-либо. Код, использующий экземпляр некоторого типа, никогда не должен заботиться о том, является ли этот тип интерфейсом, классом или чем-то еще. Таким образом, выставлять такую ​​деталь во имя типа бессмысленно и вредно для понимания. Тип и контракт, который он раскрывает, имеют значение! - person ColinD; 30.03.2011
comment
@Allain Lalonde Это верно только в том случае, если у вас есть и интерфейс, и все клиенты под вашим контролем, что часто бывает не так. - person starblue; 31.03.2011
comment
Кроме того, если вы идете по маршруту IFoo, разве это не должно быть CFoo для реализации, и, конечно, в случае неудачи метод выдаст EFoo. - person Robin; 01.06.2011
comment
Приставка вредит читабельности чисто субъективно. Как и большинство соглашений об именах. Более важно, чтобы ваша команда договорилась о том, что делать, чтобы кодовая база была согласованной. - person dreadwail; 10.07.2012
comment
... абстрактный класс к интерфейсу ... префикс I подразумевает переименование всех вхождений класса - чем это плохо? Помимо того факта, что инструменты делают тривиальным переименование чего-либо, изменение чего-либо из абстрактного класса в интерфейс является значительным изменением (по крайней мере, это переход от реализации к расширениям). - person Adam Parkin; 12.06.2013
comment
@AlllainLalonde Тем не менее, пока операция проста, вам придется зафиксировать множество файлов, что может вызвать путаницу. Большие коммиты по своей сути плохи. - person Johan Tidén; 04.07.2013
comment
@AlllainLalonde, некоторым инструментам манипулирования байт-кодом требуется полное имя типа в строковой форме, чтобы найти его в пути к классам. Подумайте о переименовании всех этих ссылок с помощью IDE. - person Carlos Melo; 02.09.2013
comment
Мне лично нравится подход C# с IInterface и OtherTypes (и, честно говоря, было бы так же хорошо с правильным сигилом). Я считаю, что эта согласованность помогает читабельности в целом. Переход от типа к интерфейсу и наоборот является изменением исходного кода как в Java, так и в C# — это полностью сводит на нет смысл переименования вхождений. Хорошая IDE, такая как ReSharper, может помочь вам безопасно и легко внести это изменение в базу исходного кода. - person user2864740; 25.03.2014
comment
Eclipse: Для имен интерфейсов мы следуем соглашению I для интерфейса: все имена интерфейсов имеют префикс I. Например, IWorkspace или IIndex. Это соглашение способствует удобочитаемости кода, делая имена интерфейсов более узнаваемыми. - person Ondra Žižka; 01.09.2014
comment
Префикс ухудшает читабельность. так что насчет имен в string.xml? вроде STR_CLOSE, STR_OK... - person Yousha Aleayoub; 16.04.2015
comment
@YoushaAleayoub - это тавтология, как и префикс I, бесполезное дублирование информации, которую public interface XXX говорит вам, что это Interface. То же самое с венгерской нотацией, которая не нужна в современных языках, которые не являются C и даже не C, с приличной IDE, которая может сообщить вам типы при наведении курсора на переменную. - person ; 05.05.2015
comment
Венгерская нотация также затрудняет завершение имен в среде IDE. Вы должны помнить тип и вводить префикс еще до того, как имя начнется, что я считаю серьезной неприятностью. - person starblue; 05.05.2015
comment
Из wiki.eclipse.org/Naming_Conventions Для имен интерфейсов мы следуем соглашению I-for-interface: все имена интерфейсов имеют префикс I. Например, IWorkspace или IIndex. Это соглашение способствует удобочитаемости кода, делая имена интерфейсов более узнаваемыми. - person Linuslabo; 22.05.2015

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

class User implements IUser

и

class UserImpl implements User

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

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

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

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO
person tddmonkey    schedule 12.02.2009
comment
Я думаю, вы хотели бы знать, что это DAO, поскольку он описывает общую функциональность без необходимости открывать класс. Если я просматриваю файлы классов в проекте, легко увидеть все DAO, ища *DAO - person Patrick; 12.02.2009
comment
DAO — это хорошо известный шаблон для доступа к базе данных, поэтому наличие шаблона в имени позволяет легко узнать, что делает класс, просто взглянув на его имя. P.S. Было бы лучше строго следовать нотации верблюда (AccountDao), такой как в mina.apache.org/changes-between-2x-and-1x.html - person Esko Luontola; 12.02.2009
comment
@marker, это не то же самое, что I для обозначения интерфейса. DAO сообщает вам, что класс или интерфейс является объектом для доступа к данным учетной записи, что и делает объект. Наличие I говорит вам, что это интерфейс, который не имеет ничего общего с самим объектом, а семантикой языка. - person tddmonkey; 13.02.2009
comment
Как вы это представляете, его префикс против суффикса. - person Andrei Rînea; 24.11.2010
comment
@Andrei: Нет, это семантика (DAO) против ненужного украшения языкового артефакта (я как в интерфейсе; факт, который все равно упоминается в коде интерфейса IFoo...) - person Dirk; 14.06.2011
comment
Интересное чтение: антишаблоны именования интерфейсов и классов. - person Daniel; 06.01.2015
comment
Разве это не то, что я сказал там наверху? - person tddmonkey; 06.01.2015
comment
В данном конкретном примере я не вижу смысла отделять реализацию от интерфейса. UserImpl не говорит ничего конкретного о том, как реализован User. Имя реализации должно сделать это конкретным. - person dzieciou; 18.10.2016
comment
семантический способ именования реализации и интерфейса, не может быть более согласен с вами - person mochadwi; 29.04.2021

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

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

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

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

person Avi    schedule 12.02.2009

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

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

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

person ng.    schedule 12.02.2009
comment
Мне это нравится, так как это также помогает вам перейти в режим использования интерфейсов для внешних зависимостей, а не связывать классы. - person Matt Briggs; 12.02.2009

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

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

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

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

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

person nairbv    schedule 25.05.2010
comment
Я думаю, что примеры, которые вы предоставляете для поддержки интерфейсов в качестве прилагательных, искажены, поскольку эти интерфейсы больше похожи на примеси (или черты). Таким образом, интерфейсы хороши и для прилагательных, и для существительных, но, вероятно, не для indefinite transitive verbs 8^P - person Stevel; 02.09.2016
comment
Это может быть изменено в последние годы. Документ оракула. позволяет использовать интерфейсы как типы: [ссылка] docs.oracle.com/javase/ учебник/java/IandI/interfaceAsType.html - person karlihnos; 01.06.2017

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

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

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

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

так что становится ясно -> Реализация интерфейса User UserImpl.

person Andreas Petersson    schedule 12.02.2009
comment
Использование интерфейсов помогает в разработке через тестирование. Мы столкнулись с многочисленными проблемами с моделью предметной области и тестированием, потому что решили НЕ использовать интерфейсы. Один мой друг как-то процитировал: Все есть интерфейс, он спасет вас в долгосрочной перспективе. - person hooknc; 12.02.2009
comment
если вы используете EasyMock, дополнительный интерфейс бесполезен. если вы не используете что-то вроде EM, да, тогда вам понадобится интерфейс для каждого класса, который нужен в качестве зависимости в классе, который необходимо протестировать. -› так что у вас будет более одного внедрения (тест + реальный) - person Andreas Petersson; 12.02.2009
comment
Мокирование и легкая поддержка прокси. Я уверен, что есть и другие причины для предоставления интерфейсов. - person MetroidFan2002; 13.02.2009
comment
Как я недавно сказал коллеге, внедрение интерфейса ничего не стоит сейчас, но впоследствии может сэкономить вам много времени. - person tddmonkey; 13.02.2009
comment
Если у вас могут быть другие реализации в ближайшем будущем, интерфейс будет плюсом. - person Stef; 09.09.2011
comment
Если у вас могут быть другие реализации в ближайшем будущем, интерфейс будет плюсом. Наличие интерфейса делает контракт понятным, а уже выполняя реализацию, вы можете легко подсунуть публичный метод, который вам может не понадобиться. Кроме того, хотя это не должно быть решающей причиной, использование интерфейсов помогает разделить задачи в командах с несколькими разработчиками. Например. кто-то работает над классом, используя эту реализацию, пока вы делаете ее реализацию. - person Stef; 09.09.2011
comment
Я заинтригован тем, какое соглашение об именах используют разработчики TDD, когда у них есть интерфейс только с одной (производственной) реализацией; стоит отдельного вопроса, интересно... ? - person SSJ_GZ; 05.10.2013
comment
Сказать мне, что тип является интерфейсом, нарушает мое право как клиента не знать и не заботиться о том, что это такое. Если мне нужен Foo, дайте мне Foo. Я поговорю с Фу, но не проси меня вспомнить, кто такой Фу. Я не знаю. Я не хочу знать. Так что не путайте меня, давая мне IFoo. - person candied_orange; 02.12.2015
comment
Мне не нравится, что мне может понадобиться еще один аргумент в будущем. Я предпочитаю подход YAGNI: не планируйте то, что еще не произошло. - person David Lavender; 07.10.2016
comment
Современным мок-фреймворкам не нужны интерфейсы — они могут имитировать и шпионить за конкретными объектами. - person David Lavender; 07.10.2016
comment
интерфейсы предназначены для стратегического размещения в точках, где вы ожидаете изменений. Каждый интерфейс является компромиссом возможности быть свободным от зависимости времени компиляции по крайней мере для одного указателя накладных расходов диспетчеризации времени выполнения. В большинстве случаев они не нужны, но если вы не разместите их там, где вы ожидаете изменения, вы можете легко привести свою программу в состояние, когда требуется полная переработка для удовлетворения новых требований (из-за сильной связи с нежелательными неинтерфейсными зависимостями, общие виновники будучи фреймворками и каналами ввода-вывода (например, базами данных)). - person Dmitry; 25.11.2016
comment
Есть миллионы причин иметь только одну реализацию. Чтобы описать их всех, достаточно одного слова: АБСТРАКЦИЯ. - person Sergio Daniel L. García; 10.05.2017

In C# it is

public class AdminForumUser : UserBase, IUser

Джава сказал бы

public class AdminForumUser extends User implements ForumUserInterface

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

person Matt Briggs    schedule 12.02.2009
comment
Может быть, я плохой Java-кодер, но я предпочитаю стиль C #, то есть все интерфейсы начинаются с префикса «I» :) - person davs; 14.12.2011
comment
Я не уверен, откуда вы и другие берете эту предполагаемую конвенцию. В библиотеках Java это не очевидно... - person ChiefTwoPencils; 07.02.2015
comment
Хотя это верно, проблема заключается в том, чтобы различать интерфейсы и классы внутри методов (например). то есть public void AddUser(IClient client, User user). В этом примере вы можете сказать, что клиент — это интерфейс, а пользователь — это класс. - person Hummus; 11.09.2020

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

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

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

person David Koelle    schedule 12.02.2009
comment
Если единственным пользователем, которого вы когда-либо намеревались иметь, является User, почему бы просто не использовать User вместо интерфейса? - person Carighan; 10.05.2017
comment
В некоторых архитектурах клиент/сервер клиентской стороне необходимо знать интерфейсы, не требуя реализации тяжеловесных серверов. - person David Koelle; 10.05.2017

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

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

чем это:

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

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

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

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

person KarstenF    schedule 12.02.2009
comment
Но зачем создавать соответствующий интерфейс для каждого класса в вашей программе, если вам нужны интерфейсы только для одной или двух вещей? - person LegendLength; 05.01.2016

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

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

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

person Jym Dyer    schedule 13.06.2011

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

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

person David Thornley    schedule 12.02.2009