Чи потрібно написати інтерфейс API перед реалізацією?


14

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

І якщо це так, у випадку використання сторонніх бібліотек (тобто Lidgren), чи потрібно я також загортати їх в інтерфейси та розв’язувати їх через контейнери МОК, чи все в порядку їх піддавати інтерфейсам?


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

Так, і запрограмуйте інтерфейси (або абстрактні класи з цього питання) перед їх реалізацією. Це допомагає отримати потік повідомлень від клієнта до сервера і навпаки "правильно" перед тим, як замикатись (і інвестувати в) реалізації. Дуже хороший слайд-шоу з цього питання: Як створити хороший API та чому це має значення
Мар'ян Венема

Відповіді:


8

На жаль, ви виявите, що це часто зводиться до особистих уподобань.

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

  1. Напишіть скелет програми як інтерфейси, абстрактні класи (на шпильках) та класи (також заглушені)
  2. Напишіть свої тести на ці інтерфейси та заглушки (вони зараз не спрацюють)
  3. Напишіть свої реалізації (ваші тести почнуть проходити, коли ви закінчите свою реалізацію)

Ви зосереджуєтесь на спробі написати більше "організованого" коду. Наступний TDD допоможе вам у цьому.

Деякі додаткові моменти:

  • IoC контейнери зручні. Використовуйте їх та DI стільки, скільки зможете.
  • Як обернути 3 - бібліотеки. Це послабить зв'язок між вашим кодом (кодом, яким ви керуєте) та кодом сторонньої сторони (кодом, яким ви не керуєте)

1
Це те, що я спочатку думав, але мені сказали, що це буде порушувати принцип YAGNI. Проблема, яку я знаходжу в багатьох моїх проектах, які ніколи не закінчуються, полягає в тому, що вони швидко стають нездійсненними через кількість написаних кодами, тому що я не організовую це належним чином або не планую план нападу.
Ден Комора

яка частина порушила б ЯГНІ?
MetaFight

Обтікання сторонніх бібліотек.
Ден Комора

2
Я думаю, це зводиться до: Які зміни шансів сторонньої бібліотеки змінюються? Якщо є 0% шансу на це, тоді впевнений YAGNI. Але так трапляється рідко. Крім того, загортання сторонніх ліфтів може полегшити ваш інший код простішим тестуванням (якщо, наприклад, ви не змогли знущатися над третьою партією бібліотеки)
MetaFight

1
@DanPantry: Обгортка сторонніх бібліотек не є порушенням YAGNI, а дуже потрібним захистом від "зараження власним кодом бібліотекою сторонніх організацій". Йдеться не лише про можливість заміни бібліотеки, але як MetaFight також говорить про захист від змін у новіших версіях бібліотеки, які в іншому випадку вимагатимуть змін у вашому власному коді. Обгортаючи бібліотеку (і особливо її конкретні типи: класи, перерахунки, структури тощо), ви ізолюєте власний код і маєте єдину точку, яку потрібно змінити, коли бібліотека змінюється (з будь-якої причини).
Мар'ян Венема

13

Так, вам слід кодувати інтерфейси, а не відомі реалізації, і так, ви повинні спочатку побудувати інтерфейси, а не виходити з власного коду.

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

Звідси випливає, що хороша інженерія програмного забезпечення багато в чому полягає в тому, як досягти бажаного ефекту (правильне обчислення з розумною ефективністю) таким чином, що дозволяє згодом працювати з вихідним кодом. Інтерфейси та API - важлива частина цієї дисципліни: вони дозволяють думати про проблему на одному рівні опису одночасно. Це набагато простіше, ніж одночасно думати про правила узгодженості бізнесу та про реалізацію пов'язаних списків, і тому насильно нав'язувати таке розмежування проблем краще ніж дозволяти клієнтському програмісту використовувати ваш код будь-яким способом, який йому подобається.

У це важко повірити багатьом програмістам-ковбоям, які впевнені, що вони розуміють усе, про що вони пишуть, набагато краще, ніж середні мислителі, і можуть впоратися з усією складністю, яка створює проблеми «меншим» програмістам. Не усвідомлення власних когнітивних меж є надзвичайно поширеним явищем - саме тому кращі практики в організації коду настільки важливі (і так часто ігноруються).

Повторимось, інтерфейси та бар'єри API - це дуже добре , навіть коли ви співпрацюєте лише з собою. Що стосується зовнішніх бібліотек, якщо вони принесуть продуманий API із собою, я не бачу жодної проблеми в його використанні, оскільки він не передбачає заміни цієї бібліотеки на іншу. Інакше обгортковий або антикорупційний шар може бути дуже хорошою ідеєю.


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

Чи існує угода про іменування для API, які є лише інтерфейсами, які я в кінцевому підсумку використовую в усьому світі? Мовляв, якщо я роблю командний зразок, чи називаю це "командними"?
Снуп

@StevieV Існують різні, наприклад IBlahреалізовані Blahабо Blahреалізовані BlahImpl. Мені не подобається і те , і , як правило, використовують Blahздійснюється OralBlah, WrittenBlahабо ASLBlah. Але, як завжди, важливіше відповідати наявній кодовій базі та очікуванням, ніж будь-якому загальному стандарту.
Кіліан Фот

4

Замість того, щоб по-рабськи просто програмувати інтерфейси, чому б не заглянути в тестові керовані розробки / дизайн (TDD)?

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

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

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

Що стосується використання сторонніх бібліотек, я б настійно рекомендував обгортати їх у власних абстракціях, де це доречно; і не дозволяйте клієнтам вашого API "знати" про них.

Щасти!

[редагувати: побачив відповідь мегапольоту - повністю згоден]


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

1
Це чудова відповідь. +1 за те, що я запропонував TDD, що, на мою думку, є вирішенням реальної проблеми ОП з того, з чого почати роботу над новим проектом, і я поставив би +1 ще раз, якщо зможу "Використання TDD змусить вас вивчити, де такі інтерфейси важливі, і де це, чесно кажучи, не має значення ".
Бенджамін Ходжсон

2

Я думаю, що це надмірно. Якщо користувача вашого API не потрібно змушувати реалізовувати / використовувати щось певним чином, то я б це не залишав. Інтерфейси - це договори, якщо мені це не потрібно, то навіщо мені його давати?

Я думаю, що люди зловживають інтерфейсами. Ви додаєте шар складності, який не потрібен у більшості випадків.


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

1

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

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.