Інтерфейси всюди? - Кращі практики

На роботі обговорюється питання правильного використання інтерфейсів в ООП. Мене вчили, і завжди працювали з передумови, що інтерфейси передують конкретизаціям і всі методи повинні мати справу з контрактами. Це роз'єднання 101 зі мною.

Я знайшов, що застосування цієї моделі універсально вчить молодших розробників канатів, встановлює мене для успіху по дорозі ("о! Все це щільно поєднується! . Це просто (і варто) зрозуміти, що ми завжди, весь час займаємося контрактами.

Інший хлопець говорить, що абстракція повинна застосовуватися тільки тоді, коли існує декілька реалізацій, і що робити це весь час робить незрозумілим для команди. Для мене це не хвилює; D це лише заплутано спочатку і швидко стає другою природою, і для мене це просто правильний спосіб будівництва.

Але я хотів потягнути руку, щоб побачити, чи хтось міг би надати деякі посилання/експертні тексти, які пояснюють, чому або чому ні.

2
Я думаю, що "абстракція" має декілька і різних значень у програмній інженерії. Для мене інтерфейси не мають нічого спільного з абстракціями. Абстракції не мають нічого спільного з деталями реалізації. Це пов'язано з дизайном. Концептуалізація. Щось, що можна досягти з інтерфейсами або без них.
додано Автор glacier, джерело
Основна небезпека створення інтерфейсу з одного класу полягає в тому, що ви отримаєте його жахливим. Уявіть собі, якщо древній австралійський визначає інтерфейс для IMammal. Усі вони матимуть необхідний метод sizeOfPouch() ...
додано Автор MrG, джерело
Поясніть, чому саме Y має вигоду від абстрактного класу. Абстракція ідентична правильному? Немає змін коду. Є виклики конструктора в мільйонах місць, маючи на увазі, що класи не повинні надавати конструкторів? Ін'єкція залежностей набагато старше, ніж C# і Java.
додано Автор Frank Hileman, джерело
Я не бачу вашої логіки. Якщо API ідентичний, підкачка є безперервною, незалежно від використання інтерфейсу, конкретного класу або абстрактного класу. Єдиною відмінністю є конструкція, яка може бути виділена різними способами, а не тільки через DI.
додано Автор Frank Hileman, джерело
InterfaceB надає значення тільки тоді, коли ви використовуєте обидві служби одночасно (багаторазове успадкування) в одному процесі. Але ви також можете отримати цю вигоду, використовуючи базовий клас.
додано Автор Frank Hileman, джерело
Якщо замінити один тип на інший, ви або використовуєте базовий клас, або зміните оригінальний тип. Будь-яка мова OO буде працювати. Ви описуєте ситуацію, коли вам потрібні обидва типи одночасно, або існують різні компоненти для авторизації (плагіни).
додано Автор Frank Hileman, джерело
Ви не надали жодного пояснення для цього твердження. Я кажу вам з точки зору користувача, єдина різниця між інтерфейсом (спеціалізованим класом) і класом - це конструктор. Вам доведеться навести приклад, коли це змінюється мільйонами.
додано Автор Frank Hileman, джерело
Загалом, дорогі зміни не змінюють назви типів, а інвазивні зміни API. DI та інтерфейси нічого не допомагають. Ваш сценарій не пов'язаний із збереженням роботи.
додано Автор Frank Hileman, джерело
Я витрачав багато часу на видалення зайвих інтерфейсів, тому я позначаю його дизайном культового вантажу. Єдина вигода полягає в збільшенні витрат на розробку програмного забезпечення - можливо, для підрядників і працівників, але не для людей, які платять за розробку.
додано Автор Frank Hileman, джерело
@froodley Правильно, але клас на таких мовах є як абстракцією (наданими операціями), так і реалізацією в одному текстовому документі. Тобто. в той час як на інших мовах вони можуть бути окремими, такі мови дозволяють об'єднати їх в одну одиницю. Вони все ще можуть бути розділені ... клас може залишити учасників нереалізованими; якщо все так, це еквівалентно інтерфейсу, без переваг успадкування.
додано Автор Frank Hileman, джерело
Класи, у яких ти мовах маєш на увазі, - це як абстракції, так і реалізації цієї абстракції. Класи надають “інтерфейс” (API). Ключове слово interface дає змогу вказати клас без реалізації, щоб усунути обмеження мови. З точки зору користувача, ні клас, ні інтерфейс не є кращими або більш абстрактними, ніж інші. Інтерфейси можуть зробити будівництво більш складним.
додано Автор Frank Hileman, джерело
Здається, ви не використовуєте однакову термінологію, що використовується в комп'ютерній науці в цілому. Класи - абстракції, навіть цілі числа і числа з плаваючою точкою - абстракції. Інтерфейси не збільшують "абстракцію": більш абстрактний тип даних - це той, який є більш загальним і вище в ієрархії типів; розташування реалізації не має значення з точки зору абстракції.
додано Автор Frank Hileman, джерело
@Meo Я згоден, інтерфейси на таких мовах призначені тільки для багаторазового успадкування. Але мені не подобається зловживання "абстракцією" в цьому питанні.
додано Автор Frank Hileman, джерело
Що стосується "роз'єднання 101" у початковому повідомленні, інтерфейс, що відповідає загальнодоступним членам класу 1: 1, нічого не відокремлює, тому що існує лише одна реалізація (тобто, пов'язана з одним класом досі), а тому при зміні підписів громадськості потрібно оновлювати їх одночасно. У той же час, немає ніякої вигоди від роз'єднання чогось, що повинно бути пов'язане - розв'язка для ситуацій, коли зв'язок є проблемою. Зайві інтерфейси - це форма дизайну культових вантажів.
додано Автор Frank Hileman, джерело
@froodley Конструктор може бути наданий тільки класом, але клас також не повинен надавати. Чи є клас без жодного "конкретного" конструктора? Користувачам не важливо, де лежить впровадження; вони працюють тільки з абстракцією.
додано Автор Frank Hileman, джерело
@froodley Що ви маєте на увазі під "бетоном"? Терміни в комп'ютерній науці, абстрактний тип даних і рівні абстракції не мають нічого спільного з ключовим словом "abstract" в Java і C #. Ключове слово буде краще називатися "unimplemented" або у випадку класу "неповний". Ви маєте на увазі тип даних, який надає конструктор? Абстракція є більш формально набором операцій, а також семантикою цих операцій; мовами, про які ми говоримо, ми можемо лише вказувати семантику в документації. Всі типи даних - абстракції - реалізація не враховується користувачами.
додано Автор Frank Hileman, джерело
Ви заплутали "інтерфейс" і "конкретність" в умовах розробки програмного забезпечення з "інтерфейсом" і "класом" в Java/C #? Ви можете запрограмувати інтерфейс, не створюючи окремого Java інтерфейсу .
додано Автор immibis, джерело
Я не згоден з тим, що конкретний клас є абстрактним. Ви маєте на увазі, що це шматок комп'ютерного коду, а не автомобіль? Я маю на увазі абстракцію в тому сенсі, що я маю справу з чимось суто абстрактним, як набір полів і операцій, які він повинен мати, узгоджений спосіб говорити про об'єкт, який не залежить від отримання якої-небудь конкретної реалізації. Все, крім чисто абстрактного класу, вже не є абстракцією, за винятком того, що це насправді не автомобіль.
додано Автор Dave Lau, джерело
Абстракція не може бути реалізацією за визначенням.
додано Автор Dave Lau, джерело
Альтернатива: Сервіс X вводиться безпосередньо скрізь. Вона більше не працює. Кожен споживач вниз повинен бути змінений, деякі в інших компаніях, деякі в програмному забезпеченні, розробленому розробниками, які залишили компанію.
додано Автор Dave Lau, джерело
Знову ж таки, якщо ви коли-небудь проводили кілька років і мільйони зверталися до чиїсь програми YAGNI, ви можете зрозуміти, чому я не згоден.
додано Автор Dave Lau, джерело
Що стосується культу вантажу, я дійсно не погоджуюся, що це не слугує меті. Я вважаю, що ви правильно займаєтеся абстракціями, а не конкретними реалізаціями, і те, що ви говорите, як сказати, що налаштування URL-адрес замість жорсткого кодування є культом вантажу, тому що вони, ймовірно, не зміняться.
додано Автор Dave Lau, джерело
Якщо ви коли-небудь були на неправильному кінці того, що ваше програмне забезпечення оголошено щільним зв'язком, і це буде коштувати мільйони разів, ви зрозумієте, що я відмовляюся від розробки жорстко пов'язаного програмного забезпечення. Робота в інтерфейсах безумовно роз'єднує ваше програмне забезпечення навіть з однією реалізацією. Будь-який споживач може замінити вашу бібліотеку іншою, яка забезпечує будь-яку реалізацію або фасад над власною реалізацією, що забезпечує той самий інтерфейс. Я дійсно не знаю, звідки ви йдете; все це схоже на лінь і мій.
додано Автор Dave Lau, джерело
Все в комп'ютері є абстракцією.
додано Автор Dave Lau, джерело
Інтерфейс є більш абстрактним, ніж конкретний клас, за визначенням.
додано Автор Dave Lau, джерело
Це концептуальне представлення об'єкта, а не конкретна реалізація цього концептуального представлення.
додано Автор Dave Lau, джерело
Якщо я скажу, що ви повинні дати мені ServiceX об'єкт, я не можу дати вам об'єкт ServiceY. Компілятор запобігає цьому. Якщо я скажу, що ви повинні дати мені об'єкт InterfaceB, ви можете дати мені будь-який.
додано Автор Dave Lau, джерело
Це спочатку збільшує витрати спочатку, зберігаючи мільйони, коли прийшов час замінити бібліотеку, яка наразі має десятки споживачів.
додано Автор Dave Lau, джерело
Якщо замінити один тип на інший, я нічого не зміню, але який завод я надаю інжектору в конфіг. Він розвертає інший клас, який реалізує інтерфейсB, і код взагалі не змінюється.
додано Автор Dave Lau, джерело
Служба X була застаріла, оскільки замінена система резервного копіювання. Служба Y створена для того, щоб служити тій самій меті. Ми надаємо службу Z інжектору залежностей, і діти з декількох бібліотек і додатків, очікуючи лише служби, яка задовольняє інтерфейс B, повністю не впливають.
додано Автор Dave Lau, джерело
На якій мові ви працюєте? Ви не можете ввести ServiceY в клас, який очікує ServiceX на будь-якій сильно типізованій мові.
додано Автор Dave Lau, джерело
Ми надаємо послуги Y *
додано Автор Dave Lau, джерело
@FrankHileman точно, OP в основному робить 2 інтерфейси для однієї реалізації, коли він повинен бути протилежним - 1 інтерфейс для 2 + реалізацій.
додано Автор Michael, джерело
@froodley в мові ви працюєте?
додано Автор Michael, джерело

5 Відповіді

Я не хочу навіть знати, чи використовую я інтерфейс (тип ключового слова). Моя функція диска приймає автомобіль. Чи є це конкретним чи ні, це не будь-який його бізнес.

Ось чому я роздратований умовою ICar C #. Отримати безглуздий шум I у моєму обличчі. Java не набагато краще. Звичайно, за згодою, я можу назвати інтерфейс, абстрактний клас або конкретний клас Автомобіль у вихідному коді, але якщо я перейду з одного на інший, я повинен перекомпілювати все, що використовує !

Все, що я хочу, це виразити те, що потреби в drive() є в системі типу. У мене немає жодного бажання, щоб drive() знав, про що він говорить, знаючи, що все, що він є, він вміє слухати.

До речі, якщо у вас є хороші тести, мова з набором качок дає вам все це безкоштовно.

Але так як я повинен використовувати ці мови, як я знаходжу їх, я, як правило, використовую рольові інтерфейси в них. Це означає, що я не пишу drive (автомобіль автомобіля) , я пишу drive (DriverControls driverControls) і все, що хоче прийняти керування, прискорення і розрив повідомлень через Протокол DriverControls є вільним для цього.

Так що якщо це те, про що ви говорите, я з вами. Якщо ви один з тих фанатиків, які наполягають на тому, що у кожного класу, як Car , є ICar , ви можете перейти в озеро.

6
додано
В Java ваш інтерфейс DriverControls зазвичай називається Drivable.
додано Автор Alexei, джерело
@froodley Домовилися. Це означає, що справжні дебати повинні стосуватися проблем, які можуть бути спричинені, коли ви вперше використовуєте конкретні класи, а потім рефакторуєте їх на інтерфейси. Це важко зробити і поважати відкритий закритий принцип. Ще гірше те, як легко поширюватись на розуміння конкретного статусу Car . Я досліджував, що намагаюся очолити це, залишаючись при цьому конкретним тут . Це не досить.
додано Автор candied_orange, джерело
В основному з тієї причини, яку ви дали, я є. Я не хочу займатися якоюсь конкретною річчю, яка називається «Автомобіль», яка робить деякі речі певним чином. Для мене це лише одноразовий, кошик для сміття. Я хочу займатися взаємодією з контрактом. Я знаю, що я отримую, знає про .drive() і .steer (), і повертає мені рядок, і мені не потрібно знати, чи це автомобіль або човен.
додано Автор Dave Lau, джерело

Вам не вистачає однієї великої частини головоломки:

Використання інтерфейсів у всьому світі робить ваш код набагато складнішим для навігації

Припустимо, у вас є велика кодова база з сотнями класів, які зросли за ці роки.

Зазвичай, коли ви хочете знати, що відбувається в методі, просто натисніть на неї, і IDE перейде до свого коду ... тобто, якщо це клас. Якщо це інтерфейс, ви переходите до інтерфейсу, то вам доведеться з'ясувати, який клас instanciated, і це може зайняти деякий час, і піти туди, і зайти в інший його метод і знову приземлитися на інтерфейс, так ви повинні знову з'ясувати, що насправді було встановлено, що може зайняти деякий час, і т.д.

В основному, навігація кодом стає все більш розчаровуючим через надмірних інтерфейсів.

Моє правило: використовувати інтерфейс, коли ви дійсно маєте декілька різних реалізацій, а не тільки заради цього .


EDIT:

Моє "набагато складніше", мабуть, перебільшено. Я б просто написав "важче" або "неперевершене".

Щоб проілюструвати це, в затемненні. З методом з класу:

  • Ctrl + клацання переходить у метод (1 клік).

З методом з інтерфейсу це буде:

  • Ctrl + клік
  • перейти вгору
  • клацніть правою кнопкою миші на назві інтеркасу
  • відкритий тип провідника
  • виберіть клас
  • відкрити контур
  • перейти до методу

... Так, так, ви можете зробити це з хорошою підтримкою IDE, але це все ще дуже дратує.

3
додано
Привіт! Слідкуйте, хлопці! ;) Моє "набагато складніше" було, мабуть, перебільшено. Я б просто написав "важче" або "неперевершене". Щоб проілюструвати це, за допомогою методу класу в eclipse, Ctrl + клацання перескакує всередині методу (1 клік). З інтерфейсом, це буде Ctrl + клік, переміщення вгорі, клацніть правою кнопкою миші на ім'я interace, відкритий тип explorer, виберіть клас, відкрийте план, перейдіть до методу. Так, так, ви можете зробити це з підтримкою IDE, але це все ще 7 кліків або близько того, що все ще дуже дратує.
додано Автор TLS, джерело
@froodley: IMHO, додавання інтерфейсів систематично це просто додавання марного шуму. Вона не покращує розмежування, а також не гарантує, що базове впровадження дотримується контракту. Вона лише додає непотрібні напрямки, шум і дратує розробників. Є багато випадків, коли інтерфейси корисні, але застосування систематично ІМХО просто дурне.
додано Автор TLS, джерело
@froodley Чи використовується бібліотека інтерфейсів або класів, я прив'язую себе до них. Я не маю значення. Якщо я називаю myLib.doThat (someArg) , не має значення, чи є myLib інтерфейсом або класом. Якщо я дійсно що залишився дещо незалежний від цього, я би мусив побудувати обгортку навколо це. Проте в більшості випадків додавання таких абстракцій є більш перешкодою, ніж корисною. Досить рідко перемикати залежності, і якщо ви це зробите, ви зазвичай помічаєте, що ваша обгортка не відповідає іншим бібліотекам дуже добре, що призводить до змін у двох місцях замість одного.
додано Автор TLS, джерело
@froodley Заміна залежності: раз на кілька років. Навігація/розуміння/рефакторинг коду: кожен день. Розташуйте інтерфейси скрізь, якщо вам це подобається, мені все одно, але, будь ласка, підтримуйте свої речі в довгостроковій перспективі.
додано Автор TLS, джерело
@Meo ми не говоримо про Runnable тут, це несправний складений приклад, подібний до "що, якщо ви хочете знайти певний підклас Object ". Немає жодних проблем у пошуку конкретної реалізації MyInterface . Якщо, звичайно, ви вирішили, що всі користувацькі класи впроваджуватимуть MyInterface без будь-яких причин, але тоді існують великі проблеми.
додано Автор Kayaman, джерело
@Meo Було б реалістично лише в ситуації, коли правило - "кожен клас повинен реалізовувати інтерфейс", без будь-яких умов щодо якого інтерфейсу. Я не бачу цього дуже ймовірно в професійному середовищі. Я маю на увазі, що якщо ми працюємо в ворожому середовищі, інтерфейси не зроблять нічого хорошого, тому що хтось може свідомо чи невідомо писати неправильні реалізації. Чи означає це, що інтерфейси марні, тому що вони не гарантують правильність реалізації?
додано Автор Kayaman, джерело
Будь-яка IDE, що стоїть на своєму солі, знає, як перейти до реалізації. Це жодним чином не є дійсною точкою, якщо ви не використовуєте погані інструменти.
додано Автор Kayaman, джерело
@Meo Я жодним чином не виступаю за те, що кожен клас потребує реалізації інтерфейсу. Необхідно чітко пояснити будь-яким молодшим розробникам, які класи вимагають інтерфейсу (наприклад, послуги), а що ні (наприклад, об'єкти, об'єкти вартості). Якщо немає архітектури або керівних принципів, то це не має значення, оскільки кодова база все одно буде в поганій формі.
додано Автор Kayaman, джерело
@Meo Я думаю, що повідомлення було змінено після мого коментаря. Я не виступаю за інтерфейси для кожного класу, і я не виступаю за таку погану архітектуру, що ви не можете стежити за тим, що відбувається.
додано Автор Kayaman, джерело
@Meo не кладе слова в мій рот, а потім скаже "Неправильно". Я кажу, що немає причин уникати інтерфейсів з однією реалізацією, наприклад. Я кажу, що не всі класи впроваджують інтерфейс, оскільки це просто нерозумно (особливо якщо це призводить до того, що всі класи реалізують Runnable через лінь). Я кажу, використовуючи свій досвід (або запитайте когось більш досвідченого) при прийнятті дизайнерських рішень. Я не впевнений, що вартість, про яку ви говорите, є вартістю розробки або витратами на виконання, але в будь-якому випадку це незначно. Це схоже на мікро-оптимізацію, уникаючи інтерфейсів.
додано Автор Kayaman, джерело
Це абсолютно має значення. Якщо ви можете замінити myLib на someLib, який реалізує той самий підпис без зміни коду взагалі, набагато менше витрачаючи 2 мільйони доларів, замінивши тисячі жорстких посилань, які ви зробили на myLib, тоді те, що я дав вам, була мовою, а не машиною. прив'язаний до вічно. Існують більш високі і більш складні та дорогі землі для розв'язки, щоб досягти навіть слабшої асоціації, але якщо ви маєте справу тільки з абстракціями, то ваше програмне забезпечення за замовчуванням дуже вільно пов'язане і може бути замінено без будь-яких змін у споживчому коді.
додано Автор Dave Lau, джерело
Це важче. Також важче не використовувати жорсткі паролі в кодовій базі або розміщувати бізнес-логіку у ваших моделях. Це стриктура. Це "ти хочеш роботу, чи ні" для мене.
додано Автор Dave Lau, джерело
Це зовсім не марно. Якщо я передаю вам клас або бібліотеку, яка займається тільки конкретизацією, ви тісно зв'язалися з моєю роботою, і ми обидва не вийшли з вікна. На моєму досвіді, це дратує нетерплячих молодших розробників, а досвідчені розробники хочуть мати справу з контрактами і розуміти, що це не самогубство.
додано Автор Dave Lau, джерело
@Kayaman ми б побачили, якщо він був відредагований, це не було.
додано Автор Michael, джерело
@Kayaman Я мав на увазі ваш перший коментар. Правда полягає в тому, що "навігація по коду стає все більш розчаровує через надмірних інтерфейсів". і жоден інструмент не може змінити це. Ви написали, що це не є правильною точкою, яка є неправильною.
додано Автор Michael, джерело
@Kayaman Ні, те, що ви говорите, що перехід від "superflous інтерфейсів" до реалізації або назад не має ніяких витрат. Неправильно.
додано Автор Michael, джерело
@Kayaman, якщо кожен клас буде мати свій власний інтерфейс, або необхідний інтерфейс з найнижчою підгонкою, то я погоджуюся з вами, що IDE має впоратися з цим просто чудово. І ви знаєте, що саме тісний інтерфейс? Сам клас. Очікуючи відсутності навігаційної вартості з перенаправлених інтерфейсів, це просто наївно.
додано Автор Michael, джерело
@ Каяман, якщо ви переросли все, то ви неминуче зіткнетеся з тією ж проблемою. Якщо наявність інтерфейсу є нормою, хтось рано чи пізно заощадить час і використовує існуючий, де вони не повинні, а потім IDE запропонує нелогічні реалізації.
додано Автор Michael, джерело
@ Kayaman Якщо ви використовуєте бідні абстракції, спробуйте знайти одну конкретну реалізацію за допомогою інтерфейсу Runnable.
додано Автор Michael, джерело

Я згоден з вашим колегою.

Створення хороших абстракцій важко. Як, дійсно, дійсно ТВОРЧИЙ!

Абстракції додають до програмного забезпечення. Вони ускладнюють навігацію кодом і пояснюють це. Вони ускладнюють зміни, оскільки зміни в абстракціях часто вимагають змін у багатьох місцях.

Інтерфейс, який просто копіює те, що має клас, не є гарною абстракцією. Тільки час, коли ви можете сказати, що у вас є хороша абстракція, це те, що ви можете собі уявити (або фактично мати) кілька різних реалізацій.

Всякий раз, коли ви створюєте абстракцію, ви повинні задати собі питання: "Чи дійсно варто ускладнювати код, щоб я міг роз'єднати ці частини?"

3
додано
Створення хороших абстракцій важко, тому що вони усувають складність. До неї додаються погані абстракції.
додано Автор Shizam, джерело
@froodley Якщо ваш інтерфейс і клас мають однаковий підпис, ви не відокремили нічого, окрім будівництва.
додано Автор Frank Hileman, джерело
Створення великих абстракцій є важким, створення абстракцій, які служать меті розв'язки, не є таким важким. Якщо мої споживачі можуть замінити мій модуль або клас іншим модулем або класом, який може служити до того ж підпису, я відчуваю, що я виконав роботу правильно і вони не тісно пов'язані з тим, що я зробив.
додано Автор Dave Lau, джерело

Роз'єднання не є непоганим. Це тільки хороша річ, де вам це потрібно, і погано скрізь. Якщо ви використовуєте інтерфейс на місці, де повинна бути висока згуртованість, то ви робите це неправильно.

Кожен інтерфейс має вартість і цінність, якщо ви не розглядаєте його і сліпо робите їх скрізь, то ви робите це просто неправильно.

1
додано
@froodley Контракт - це набір операцій і семантики. Інтерфейс - це просто набір операцій, набір сигнатур, який виглядає точно так само, як клас, з точки зору користувача. Наскільки я можу сказати, те, що ви називаєте "бетоном" - це наявність конструктора в класі. Розв'язка означає, що ви можете змінювати API незалежно від реалізації. Клас може зробити це, інтерфейс може зробити це, але реальне роз'єднання означає використання декількох інтерфейсів або динамічної мови.
додано Автор Frank Hileman, джерело
@froodley З точки зору користувача, єдина різниця залежностей між тим, що ви називаєте "конкретним" класом і "інтерфейсом", є залежністю від конструктора. Можна побудувати клас, який надає конструктор. Ви не можете побудувати спеціалізовані класи, які не надають конструктор, наприклад інтерфейс. Інтерфейс і клас ідентичні з точки зору користувачів, інакше.
додано Автор Frank Hileman, джерело
Це ваш погляд, мій - навпаки. Концептуально висока згуртованість модуля все ще досягається, коли ви маєте справу з тісно пов'язаними контрактами. Я вважаю, що будівництво, засноване на контрактах, весь час знімає будь-яку неоднозначність і забезпечує належне мислення, в той час як кодова база з високою мірою "для дешевих" у порівнянні з спробою роз'єднатися пізніше, коли багато споживачів вже залежать від вашого конкрементів. Але знову ж таки, я шукаю посилання на матеріал для читання на цю тему.
додано Автор Dave Lau, джерело
Інтерфейс - це контракт. Клас - це машина, яка виробляє деяку реалізацію цього контракту. Це дуже, дуже різні. Я взагалі не переконаний, що робота з конкретними машинами є такою ж, як у контрактах.
додано Автор Dave Lau, джерело

Програму даних бізнес-додатків

Як правило, вони не є класичними для класичної "істинної" ООП, де об'єкт реалізує власну поведінку через всі ділові правила, які залежать від поточного підключеного користувача і так далі. Замість цього у мене є добре відома анемічна модель + послуги, тому що я не знайшов нічого, що більше підходить для моїх потреб, за винятком деяких незалежних технічних компонентів.

Мої сервіси завжди мають інтерфейси, тому що навіть якщо я маю одну реалізацію, буде час, коли я хочу знущатися з ними. Я абстрактно трохи, але не надто багато, оскільки в той час я роблю це, я не знаю, що багато чого я можу потребувати і як це зробити правильно, і мій час краще, що витрачати час на це (YAGNI/KISS) ).

Звичайно, оскільки я починаю з однієї реалізації, мій інтерфейс в значній мірі є копією того, що моя реалізація повинна виставляти, але це спеціально. Якщо мені потрібно мати іншу реалізацію, яка за своєю природою змусить мене рефакторувати мій інтерфейс до більш загального, і я зроблю це, коли це необхідно.

Примітка: я використовую звичайну назву для інтерфейсу моїх служб, які я використовую (не "я" або будь-який інший), тому що споживач цих послуг дійсно не хвилює, що вони інтерфейси, як сказано @candied_orange

0
додано
На Java ви можете знущатися без інтерфейсів точно так само, як з ними (використовуючи Mockito та ін.), Якщо не хочете, звичайно, реалізувати клас вручну.
додано Автор Michael, джерело