Наименуване на интерфейс в Java [затворено]

Повечето OO езици добавят префикс към имената на интерфейса си с главно I, защо Java не прави това? Каква беше причината да не спазвате тази конвенция?

За да демонстрирам какво имам предвид, ако исках да имам потребителски интерфейс и потребителска реализация, щях да имам два избора в Java:

  1. Клас = потребител, интерфейс = потребителски интерфейс
  2. Клас = UserImpl, интерфейс = потребител

Къде на повечето езици:

Клас = потребител, интерфейс = IUser

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

И така, предполагам, че въпросът ми се свежда до: „Струва ли си да следваме по-широката конвенция за именуване на интерфейса, особено в светлината на това накъде изглежда се насочва Java Frameworks?“


person Allain Lalonde    schedule 12.02.2009    source източник
comment
Къде на повечето езици? Кои езици освен тези на .Net?   -  person wds    schedule 12.02.2009
comment
Не всички .NET също; C++ е използваем .NET език и сам по себе си няма интерфейси (абстрактните базови класове могат да идват с известна реализация). Този въпрос свежда ли се до защо Java не е като C#??   -  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 префикс, напр. IUnknown, IStream. В C++ беше обичайно да има IStream* и други подобни при взаимодействие с COM. Изглежда като естествено разширение на C- префикса за класове, въпреки че намирам за интересно, че .NET е изоставил класовите префикси. Delphi използва същата конвенция както за собствените си интерфейси, така и за използването на COM интерфейси. Лично аз нямам нищо против конвенцията. Въпросът на OP тук показва част от разочарованието от конвенциите за именуване на интерфейси на 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, ако трябваше да следват собствената си конвенция, това би било Interface[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 предполага преименуване на всички срещания на класа - защо това е лошо? Освен факта, че инструментите правят тривиално преименуването на нещо, промяната на нещо от абстрактен клас в интерфейс е значителна промяна (ако не друго, това е промяна от implements към extensions). - person Adam Parkin; 12.06.2013
comment
@AllainLalonde Въпреки че операцията е лесна, ще трябва да ангажирате изобилие от файлове, което може да причини объркване. Големите ангажименти по своята същност са нещо лошо. - person Johan Tidén; 04.07.2013
comment
@AllainLalonde, някои инструменти за манипулиране на байт код се нуждаят от пълното квалифицирано име на тип под формата на низ, за ​​да го намерят в пътя на класа. Помислете за преименуване на всички тези препратки с IDE. - person Carlos Melo; 02.09.2013
comment
Аз лично харесвам подхода на C# с IInterface и OtherTypes (и честно казано щеше да е също толкова добре с подходящ сигил). Намирам, че тази последователност помага за четливостта над всичко. Промяната от тип към интерфейс и обратно е промяна, нарушаваща източника както в Java, така и в C# - това напълно отрича смисъла от преименуване на събития. Една добра IDE като ReSharper може да ви помогне да направите тази промяна безопасно и тривиално чрез базата на изходния код. - person user2864740; 25.03.2014
comment
Eclipse: За имена на интерфейси следваме конвенцията I-for-interface: всички имена на интерфейси са с префикс 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 предпочита по-дълги имена с действителни значения пред префикси в унгарски стил. Така че този код ще бъде възможно най-четлив: списъкът представлява списък, а потребителят представлява потребител - не 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

Както каза друг плакат, обикновено е за предпочитане интерфейсите да дефинират възможности, а не типове. Бих склонил да не "имплементирам" нещо като "Потребител" и това е причината "IUser" често да не е наистина необходим по начина, описан тук. Често виждам класовете като съществителни, а интерфейсите като прилагателни:

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

Понякога прилагателното няма смисъл, но все пак обикновено използвам интерфейси за моделиране на поведение, действия, възможности, свойства и т.н., не типове.

Освен това, ако наистина смятате да създадете само един потребител и да го наречете потребител, тогава какъв е смисълът да имате и интерфейс IUser? И ако ще имате няколко различни типа потребители, които трябва да внедрят общ интерфейс, какво ви спестява добавянето на „I“ към интерфейса при избора на имена на реализациите?

Мисля, че по-реалистичен пример би бил, че някои типове потребители трябва да могат да влизат в определен API. Можем да дефинираме интерфейс за влизане и след това да имаме родителски клас „Потребител“ със сукласове SuperUser, DefaultUser, AdminUser, AdministrativeContact и т.н., някои от които ще имплементират или не интерфейса за влизане (с възможност за влизане?), ако е необходимо.

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

Боб Лий каза веднъж в презентация:

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

така че започвате с една реализация, т.е. без интерфейс. по-късно решавате, добре, тук има нужда от интерфейс, така че преобразувате вашия клас в интерфейс.

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

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

person Andreas Petersson    schedule 12.02.2009
comment
Използването на интерфейси ще помогне за тестване на разработката. Сблъскахме се с множество проблеми с нашия модел на домейн и тестване, защото решихме да НЕ използваме интерфейси. Един мой приятел веднъж цитира: Всичко е интерфейс, това ще ви спаси в дългосрочен план. - person hooknc; 12.02.2009
comment
ако използвате EasyMock, няма реална полза от допълнителен интерфейс. ако не използвате нещо като EM, да, тогава ще ви трябва интерфейс за всеки клас, който е необходим като зависимост в клас, който трябва да бъде тестван. -› така че ще имате повече от един impl (test+real) - 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'ers, когато имат интерфейс само с една (производствена) реализация; струва ли си въпрос сам по себе си, чудя се...? - person SSJ_GZ; 05.10.2013
comment
Казвайки ми, че даден тип е интерфейс, нарушава правото ми като клиент да не знам или да не се интересувам какво представлява. Ако имам нужда от Фу, дайте ми Фу. Ще говоря с Фу, но не ме молете да си спомням какво е Фу. Не знам. не искам да знам Така че не ме обърквайте, като ми давате IFoo. - person candied_orange; 02.12.2015
comment
Не ми харесва може да се нуждая от друго внушение в бъдещ спор. Предпочитам подхода YAGNI: не планирайте неща, които все още не са се случили. - person David Lavender; 07.10.2016
comment
Съвременните подигравателни рамки не се нуждаят от интерфейси - те могат да подиграват и шпионират конкретни обекти - person David Lavender; 07.10.2016
comment
интерфейсите са предназначени да бъдат стратегически разположени в точки, където очаквате промяна. Всеки интерфейс е компромис от способността да бъде освободен от зависимостта от времето за компилиране за поне един указател на режийни разходи за изпращане по време на изпълнение. В повечето случаи те са ненужни, но ако не ги поставите там, където очаквате промяна, можете лесно да поставите програмата си в състояние, в което се изисква пълно пренаписване, за да отговори на новите изисквания (поради тежко свързване с нежелани неинтерфейсни зависимости, често срещани виновници като рамки и io канали (напр. бази данни)). - 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

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

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

от това:

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

Ако следвате тази идея, твърдя, че кодът ви ще бъде по-четлив, ако дадете имена на интерфейси като „Потребител“ и „Банкова сметка“ (например), вместо „IUser“, „UserInterface“ или други варианти.

Единствените битове код, които трябва да се интересуват от действителните конкретни класове, са местата, където са конструирани конкретните класове. Всичко останало трябва да бъде написано с помощта на интерфейсите.

Ако направите това, тогава "грозните" конкретни имена на класове като "UserImpl" трябва да бъдат безопасно скрити от останалата част от кода, който може весело да продължи да използва "хубавите" имена на интерфейси.

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

=v= Префиксът "I" също се използва в рамката на Wicket, където свикнах бързо. Като цяло приветствам всяка конвенция, която съкращава тромавите имена на класове в Java. Трудно е обаче, че всичко е подредено по азбучен ред под "I" в директориите и в Javadoc.

Практиката за кодиране на Wicket е подобна на Swing, тъй като много екземпляри на контроли/приспособления са конструирани като анонимни вътрешни класове с вградени декларации на методи. Досадно е, че се различава на 180° от Swing по това, че Swing използва префикс ("J") за внедряващите класове.

Наставката „Impl“ е небрежно съкращение и не се интернационализира добре. Ако поне бяхме избрали „Imp“, щеше да е по-сладко (и по-кратко). „Impl“ се използва за IOC, особено Spring, така че засега сме останали с него. Все пак става малко шизо след 3 различни конвенции в три различни части на една кодова база.

person Jym Dyer    schedule 13.06.2011

Това по-широка конвенция за именуване ли е в някакъв истински смисъл? Аз съм по-скоро на страната на C++ и не съм наясно с Java и потомците. Колко езикови общности използват I конвенцията?

Ако имате тук независима от езика конвенция за именуване на магазина, използвайте я. Ако не, продължете с конвенцията за именуване на езика.

person David Thornley    schedule 12.02.2009