Що мав на увазі Річ Хікі, коли він сказав: "Вся ця специфіка [інтерфейсів / класів / типів] вбиває ваше повторне використання!"


41

У 29-хвилинній програмі Річ Хікі, що викликає роздуми на готовій конференції, " Значення цінностей ", він говорить про накладні витрати на мову, як Java, і робить заяву на кшталт "Усі ці інтерфейси вбивають ваше повторне використання". Що він означає? Це правда?

У пошуках відповідей я натрапив на:

  • Принцип найменших знань AKA Закон Деметера, який заохочує герметичні інтерфейси API. У Вікіпедії також вказані деякі недоліки.

  • Криза імперської одягу Кевліна Генні, яка стверджує, що використання, а не повторне використання, є відповідною метою.

  • Розмова Джека Дідеріха " Зупини писати класи ", яка заперечує проти надмірної інженерії взагалі.

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

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


1
Я не переглядав / не читав матеріали (я додав "Зупинити писати класи" у свій список перегляду :)), але, можливо, вони сперечаються з динамічного проти статичного кута введення тексту? ... знову?
Андрес Ф.

oO Інтерфейси програмування прикладних програм
Томас Едінг

Дякуємо за посилання! Я не вважав розмови Джека Дідеріха особливо яскравими (дивіться, як він не зможе переконливо відповісти на справжні запитання аудиторії .. "е, так, можливо, у такому випадку ...". Мені подобалося, що він, схоже, сперечається про функціональне програмування без навіть помічаючи це;)), але «Криза імператорського одягу» дуже гарна і прониклива.
Андрес Ф.

1
MPO полягає в тому, що люди, які не вірять у повторне використання, не розбивають речі на досить малі одиниці. Велика річ, побудована для однієї конкретної мети, не може бути використана повторно. Однак у дрібних речей зазвичай є досить мала мета, що маленька мета корисна у більш ніж одному контексті.
Емі Бланкенсіп

1
@AmyBlankenship Я вважав, що "криза імператорського одягу", пов'язана вище, була глибокою. Автор вважає "повторне використання" помилковим кумиром (те, що не виявилося корисним на практиці, а також більшість людей навіть не розуміють цього, хоча вони використовують це слово). Він також не вважає бібліотеки "повторним використанням"; ви використовуєте бібліотеку, не використовуєте її повторно . Він також розглядає можливість спроектувати щось для повторного використання "меча з двома кінцями"; те, що люди зазвичай вважають виграшною ситуацією, але чого насправді не так: коли ви розробляєте щось для повторного використання, це завжди компроміс (наприклад, ви можете програти в простоті)
Андрес Ф.

Відповіді:


32

Я не дивився повної презентації Rich Hickey, але якщо я правильно його розумію, і судячи з того, що він говорить про 29-хвилинну позначку, він, схоже, сперечається про типи вбивств, які повторно використовують. Він використовує термін "інтерфейс" вільно як синонім "названого типу", що має сенс.

Якщо у вас є два об'єкти { "name":"John" }типу Personта { "name": "Rover" }типу Dog, у Java-land вони, ймовірно, не можуть взаємодіяти, якщо вони не мають спільного інтерфейсу чи предка (наприклад Mammal, це означає написання більше коду). Отже, інтерфейси / типи тут "знищують ваше повторне використання": хоча Personі Dogвиглядають однаково, один не можна використовувати взаємозамінно з іншим, якщо тільки ви не вкажете додатковий код для його підтримки. Зауважте, Hickey також жартує про проекти на Java, які потребують безлічі класів ("Хто тут написав програму Java, використовуючи всього 20 класів?"), Що, здається, є одним із наслідків сказаного.

Однак у мовах, орієнтованих на цінність, тим структурам ти не призначатимеш типи; вони просто значення, які мають спільну структуру (у моєму прикладі вони мають nameполе зі значенням String) і тому можуть легко взаємодіяти, наприклад, вони можуть бути додані до однієї колекції, передані тим же методам тощо.

Підводячи підсумок, все це, здається, щось стосується структурної рівності проти явної рівності / інтерфейсу . Якщо я не пропустив щось із частини відео, якого я ще не переглядав :)


2
До речі, розмова Джека Дідеріха "Зупини писати класи", здається, не пов'язана з цією темою, і більше стосується YAGNI і "не пишіть код, поки вам це не потрібно, а тоді пишіть простий код".
Андрес Ф.

9
ERROR: Object doesn't have a property called "name"часто є результатом value-orientedмов, а інша проблема полягає в тому, коли ви більше не хочете називати цю властивість name. Успіхів рефакторингу, тому що, ймовірно, сотні об'єктів з властивістю, nameале не всі є Personабо Dog.
Реакційний

2
@MathewFoscarini Так, я не обов'язково з цим погоджуюся, це лише моя інтерпретація того, що я думаю, Хікі сказав :) Мені подобаються типи та статичні введення тексту; Я тільки починаю не любити Java. І моя неприязнь пов'язана не з interfaces, а з безладом, який є типовим проектом Java.
Андрес Ф.

1
Java - мова програмування для тих, хто вважає за краще занадто багато думати. Це одна з небагатьох мов, яка дозволяє розробнику легко приховувати свої спроби над інженером проекту.
Реакційний

"Мови, орієнтовані на цінність, ви не будете призначати типи цим структурам" - я думаю, вам потрібно сказати "У динамічному" ціннісно-орієнтованому "... Haskell і Scala орієнтовані на цінність, але їх статична система типу дає їм точну проблему, яку ви описуєте. Я думаю, що рішення цієї проблеми не стільки значення, скільки використання карт для передачі параметрів функцій. Використання незмінних карт (значень) просто безпечніше.
GlenPeterson

28

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

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

Це на зразок графічного інтерфейсу GUI, який має IWindowінтерфейс для діалогового вікна, а потім ви можете додати IButtonінтерфейси для елементів керування. За винятком того, що вони ніколи не дали тобі хорошого Buttonкласу, який реалізуєш IButton. Отже, ви залишаєте створювати свою власну.

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

Розробники Java почали робити це там, де лише їх шари API interfaces. Ви можете реалізувати ці інтерфейси, але ви ніколи не можете повторно використовувати класи від розробника, який реалізував ці інтерфейси. Це схоже на стиль плаща та кинджалу розробки API.


4
Дякую за цю відповідь. Зараз я відчуваю, що розумію питання і відповідь :)
MetaFight

2
+1 Я дуже ціную вашу відповідь, і це додає захоплюючого шару цікавої інформації до цього питання. Але я думаю, що відповідь Андреаса Ф., ймовірно, ближче до серця того, що мав на увазі містер Хікі, тому я прийняв його замість цього.
GlenPeterson

@GlenPeterson жодних проблем, я думаю, він також може бути на позначці.
Реакційний

1
Ну і ця прийнята відповідь виділяє дві трохи різні, але однаково цікаві інтерпретації. Мені цікаво, кого з містера Хікі мав на увазі, коли говорив про це ..
Девід Коуден,

Ви не можете повторно використовувати інтерфейс, але ви можете розширити його (і надати цінний номер версії) без зміни старих класів. Ви також можете успадкувати з багатьох інтерфейсів, щоб додати нове завдання для нових класів або додати нове спадкування в старі перекомпільовані класи. Ви також можете розширити клас, який реалізує цей інтерфейс для нового завдання.
cl-r

14

Я думаю, слайд 13 на його презентації ( Значення цінностей ) допомагає зрозуміти це:

http://i.stack.imgur.com/LVMne.png


Цінності

  • Не потрібні методи
    • Я можу надіслати вам значення без коду,
      і ви добре

Я розумію, Хікі пропонує, що якщо мені потрібно, скажімо, подвоїти значення, яке ви мені надіслали, я просто напишу код схожий

    MyValue = Double(YourValue)

Розумієте, вище код той самий, незалежно від того, яке значення ви надіслали - начебто ідеальне повторне використання .

Тепер, як це виглядатиме на мові, що має об’єкти та інтерфейси?

    Doublable MyValue = YourValue.Double()

чекай! що робити, якщо YourValueне реалізується Doublable? не те, що його неможливо подвоїти, це може бути ідеально, але ... що робити, якщо просто немає методу Double ? (що робити, якщо існує метод, який називається сказати TwiceAsMuch?)

О, у нас проблема. YourValue.Doubleне працюватиме, його більше не можна використовувати . На моєму читанні слайду, що йдеться вище, це приблизно те, що мав на увазі Хікі, коли він сказав: "Усі ці інтерфейси вбивають ваше повторне використання!"

Розумієте, інтерфейси припускають, що об’єкти передаються навколо "разом з їх методами", а також код, який діє на них. Щоб використовувати об'єкти, потрібно зрозуміти, як викликати цей код, який метод викликати.

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


Примітка сторони: поняття обході коди менше значень як - то мені нагадує візерунок найлегшій в об'єктно - орієнтованому програмуванні.

об’єкт, який мінімізує використання пам'яті, обмінюючись якомога більше даних з іншими подібними об'єктами; це спосіб використовувати об'єкти у великій кількості, коли просте повторне представлення використовувало б неприйнятний об'єм пам'яті ... Легкі об'єкти - це визначення об'єктів значення . Ідентичність об’єкта об'єкта не має жодного наслідку, тому два екземпляри Flyweight одного значення вважаються рівними ...

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

Це відчувається майже як на слайді, "значенням не потрібні методи. Я можу надсилати вам значення без коду, і ви добре".


5
Дженрікіс б дуже вирішив цю проблему. Подвоєння має сенс на одних об'єктах, а не на інших. У мові Go є неявна реалізація інтерфейсу (форма введення качки), тому у вас немає всіх тих інтерфейсів, щоб турбуватися. З іншого боку, ви маєте знати, на який об’єкт буде потрапляти ваш підпис методу; в іншому випадку ви можете отримати несподівані результати. Завжди є компроміси.
Роберт Харві

1
Цікавий прийом. Гарна відповідь!
maple_shaft

2
Легка вага - це не те, про що говорить Річ. Як зазначається у другому реченні статті, метою малюнка з легкою вагою є збереження пам’яті. Підхід Ріха не прагне цього робити.

5
MyValue = Double(YourValue)не має сенсу, якщо YourValue - це рядок, адреса, користувач, функція або база даних. В іншому випадку ваш аргумент відсутній метод є сильним. OTOH, методами accessor дозволяють застосовувати різні обмеження, щоб ваші Значення були дійсними, а для створення нових Значень використовувались лише розумні операції. Якщо пізніше ви вирішите відокремити адресу від свого користувача та компанії, методи доступу означають, що ви не порушите всіх клієнтів свого коду. Таким чином, вони можуть допомогти повторному використанню, навіть якщо іноді перешкоджають цьому в короткотерміновій перспективі.
GlenPeterson

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

2

У (тобто моєму) ідеальному світовому класі та інтерфейсах завжди було б описано поведінку, але факт полягає в тому, що дуже часто вони справді просто описують дані. Лише вчора я переглянув відео про те, як хтось будує так званий BankAccountклас, який був не що інше, як прославлений int(дійсно, він був набагато менш корисним ніж int, таким чином, "убив" повторне використання, яке б я його просто залишив як " int) все в ім'я "хорошого" дизайну. Кількість коду, поту та сліз, що витрачається на постійне винаходиння перекручених уявлень даних, є приголомшливим; якщо ви не використовуєте дані змістовно, то будь ласка, нехай це буде.

Тепер це етап, коли Річ Хікі задоволений, щоб викинути дитину разом з водою і сказати, що всі ми повинні їхати жити у країну цінностей (сусід з царства іменників). Я думаю, з іншого боку, що OOP може і сприяє повторному використанню (і, що важливо, відкритості, якої я вважаю відсутнім у функціональному програмуванні), коли використовується розумно. Якщо ви шукаєте принцип ООП, який найкраще сприймає це напруження, я думаю, це може бути http://c2.com/cgi/wiki?TellDontAsk (що, звичайно, є близьким двоюрідним братом Деметра)


Що ви маєте на увазі під відкриттям? Це схоже на це ?

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