Что имел в виду Рич Хики, когда сказал: «Вся эта специфика [интерфейсов / классов / типов] убивает ваше повторное использование!»

41

В 29 -минутном выступлении Рич Хики, посвященном размышлениям на конференции Goto « Значение ценностей », он рассказывает о накладных расходах такого языка, как Java, и делает следующее заявление: «Все эти интерфейсы убивают ваше повторное использование». Что он имеет в виду? Это правда?

В поисках ответов я наткнулся на:

  • Принцип Наименьшего Знания AKA Закон Деметры, который поощряет герметичные интерфейсы API. В Википедии также перечислены некоторые недостатки.

  • Кризис Имперской Одежды Кевлина Хенни, который утверждает, что использование, а не повторное использование является соответствующей целью.

  • Лекция Джека Дидерича " Остановка написания классов ", в которой высказывается аргумент против чрезмерной инженерии в целом.

Понятно, что все написанное достаточно плохо будет бесполезно. Но как интерфейс хорошо написанного API предотвратит использование этого кода? В истории есть примеры того, как что-то сделано для одной цели и используется больше для чего-то другого . Но в мире программного обеспечения, если вы используете что-то для целей, для которых оно не предназначено, оно обычно ломается.

Я ищу один хороший пример хорошего интерфейса, предотвращающего законное, но непреднамеренное использование некоторого кода. Это существует? Я не могу представить это.

GlenPeterson
источник
1
Не смотрел и не читал материал (я добавил «Остановить запись классов» в свой список просмотра :)), но, может быть, они спорят с точки зрения динамической и статической типизации? ...опять таки?
Андрес Ф.
oO Интерфейсы прикладного программирования
Томас Эдинг
Спасибо за ссылки! Я не нахожу выступление Джека Дидериха особенно осветительным (посмотрите, как он не может убедительно ответить на подлинные вопросы аудитории ... "да, может быть, в этом случае ...". Мне действительно хотелось, чтобы он выступал за функциональное программирование без даже замечая это;)), но «Кризис Имперской одежды» очень хорош и проницателен.
Андрес Ф.
1
MPO состоит в том, что люди, которые не верят в повторное использование, не разбивают вещи на достаточно маленькие единицы. Большая вещь, созданная для одной конкретной цели, не может быть использована повторно. Однако мелкие вещи обычно имеют достаточно маленькую цель, поэтому мелкая цель полезна в более чем одном контексте.
Эми Бланкеншип
1
@AmyBlankenship Я обнаружил, что «Кризис имперской одежды», описанный выше, был проницательным. Автор считает «повторное использование» ложного идола (то, что не было доказано полезным на практике, а также большинство людей даже не понимают этого, даже если они используют это слово). Он также не считает библиотеки «повторным использованием»; вы используете библиотеку, вы не используете ее повторно . Он также рассматривает создание чего-то для повторного использования "обоюдоострого меча"; то, что люди обычно считают беспроигрышной ситуацией, но на самом деле это не так: когда вы разрабатываете что-то для повторного использования, это всегда компромисс (например, вы можете потерять в простоте)
Андрес Ф.

Ответы:

32

Не смотрел полную презентацию Рича Хикки, но если я правильно его понимаю, и, судя по тому, что он говорит о 29-минутной отметке, он, кажется, спорит о повторном использовании типов, убивающих. Он использует термин «интерфейс» свободно как синоним «именованного типа», что имеет смысл.

Если у вас есть две сущности { "name":"John" }типа Personи { "name": "Rover" }типа Dog, в Java-земле они, вероятно, не смогут взаимодействовать, если у них нет общего интерфейса или предка (например Mammal, это означает написание большего количества кода). Таким образом, интерфейсы / типы здесь «убивают ваше повторное использование»: хотя Personи Dogвыглядят одинаково, один не может использоваться взаимозаменяемо с другим, если вы не напишите дополнительный код для поддержки этого. Обратите внимание, что Хикки также шутит о проектах в Java, требующих большого количества классов («Кто здесь написал приложение Java, использующее всего 20 классов?»), Что является одним из следствий вышеприведенного.

Однако в «ориентированных на значение» языках вы не будете присваивать типы этим структурам; это просто значения, которые имеют общую структуру (в моем примере оба имеют nameполе со значением String) и поэтому могут легко взаимодействовать, например, их можно добавлять в одну коллекцию, передавать в одни и те же методы и т. д.

Подводя итог, все это, кажется, что-то о структурном равенстве против явного равенства типа / интерфейса . Если только я не пропустил что-то из частей видео, которое еще не смотрел :)

Андрес Ф.
источник
2
Кстати, выступление Джека Дидериха «Остановка написания классов», похоже, не имеет отношения к этой теме, больше касается YAGNI и «не пишите код, пока он вам не нужен, а затем пишите только простой код».
Андрес Ф.
9
ERROR: Object doesn't have a property called "name"часто является результатом использования value-orientedязыков, а другая проблема возникает, когда вы больше не хотите вызывать это свойство name. Удачи рефакторинг, потому что есть, вероятно, сотни объектов со свойством, nameно не все являются Personили Dog.
Reactgular
2
@MathewFoscarini Да, я не обязательно согласен с этим, это просто моя интерпретация того, что, по-моему, говорил Хикки :) Мне нравятся типы и статическая типизация; Я только начинаю не любить Java. И моя неприязнь не связана с interfaces, но с беспорядком, который является типичным проектом Java.
Андрес Ф.
1
Java - это язык программирования для тех, кто предпочитает слишком много думать. Это один из немногих языков, который позволяет разработчику легко скрывать свои попытки перепроектировать проект.
Reactgular
«В« ориентированных на значение »языках вы не будете присваивать типы этим структурам» - я думаю, вам нужно сказать «В динамических« ориентированных на значение »...» Haskell и Scala ориентированы на значения, но их статическая система типов дает им точную проблему, которую вы описываете. Я думаю, что решение этой проблемы не столько значения, сколько использование карт для передачи параметров в функции. Использование неизменяемых карт (значений) просто безопаснее.
ГленПетерсон
28

Он, скорее всего, ссылается на тот факт, что интерфейс не может быть создан. Вы не можете reuseинтерфейс. Вы можете реализовать только код, который его поддерживает, и когда вы пишете код для интерфейса, повторное использование отсутствует.

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

Это что-то вроде инфраструктуры GUI, в которой есть IWindowинтерфейс для диалогового окна, а затем вы можете добавить IButtonинтерфейсы для элементов управления. За исключением того, что они никогда не давали вам хороший Buttonкласс, который реализует IButton. Таким образом, вы оставили создавать свои собственные.

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

Java-разработчики начали делать это там, где выставлены только их API-уровни interfaces. Вы можете реализовать эти интерфейсы, но вы никогда не сможете повторно использовать классы от разработчика, который реализовал эти интерфейсы. Это что-то вроде плаща и кинжала в стиле API.

Reactgular
источник
4
Спасибо за этот ответ. Теперь я чувствую, что понимаю вопрос и ответ :)
MetaFight
2
+1 Я очень ценю ваш ответ, и он добавляет интересный слой интересной информации к этому вопросу. Но я думаю, что ответ Андреаса Ф., вероятно, ближе к сути того, что имел в виду мистер Хикки, поэтому я принял его вместо.
ГленПетерсон
@GlenPeterson без проблем, я думаю, что он может быть на высоте.
Reactgular
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 в ООП.

объект, который минимизирует использование памяти, разделяя как можно больше данных с другими подобными объектами; это способ использовать объекты в больших количествах, когда простое повторяющееся представление будет использовать недопустимый объем памяти ... Малогабаритные объекты по определению являются объектами значений . Идентичность экземпляра объекта не имеет значения, поэтому два экземпляра Flyweight одинакового значения считаются равными ...

Использование мухи, которое я видел, как правило, следовало тому же подходу: отрывать код (методы, интерфейсы) от объектов и передавать вещи вокруг, ну, в общем , без кода значений , ожидая, что для получения кода есть средства, необходимые для работы с ними.

Это выглядит почти так же, как на слайде: «значениям не нужны методы. Я могу отправить вам значения без кода, и у вас все хорошо».

комар
источник
5
Дженерики в значительной степени позаботятся об этой проблеме. Удвоение имеет смысл для одних объектов, но не для других. В языке Go существует неявная реализация интерфейса (форма утки), поэтому вам не о чем беспокоиться. С другой стороны, вы должны знать, какой объект будет поражен сигнатурой вашего метода; в противном случае вы можете получить неожиданные результаты. Всегда есть компромиссы.
Роберт Харви
1
Интересный дубль. Хороший ответ!
maple_shaft
2
Роза в полусреднем весе - это не то, о чем говорит Рич. Как отмечается во втором предложении статьи, цель шаблона «легковес» - сохранить память. Подход Рича не стремится к этому.
5
MyValue = Double(YourValue)не имеет смысла, если YourValue является строкой, адресом, пользователем, функцией или базой данных. В противном случае ваш аргумент пропущенного метода является сильным. OTOH, методы доступа позволяют применять различные ограничения, чтобы ваши Значения были действительными, и чтобы для создания новых Значений использовались только разумные операции. Если впоследствии вы решите отделить Адрес от вашего Пользователя и Компании, методы доступа означают, что вы не нарушаете все клиенты своего кода. Таким образом, они могут помочь повторно использовать в долгосрочной перспективе, даже если они иногда препятствуют этому в краткосрочной перспективе.
ГленПетерсон
4
(С другой стороны, я согласен с тем, что в Java-стране взрыв классов, интерфейсов и сред является кошмаром. Самое простое «корпоративное» решение в Java - это беспорядок кода. Поэтому я действительно извлекаю из этого ценный урок вопрос и ответ, не обязательно соглашаясь с динамическим набором текста)
Андрес Ф.
2

В (то есть в моем) идеальном мире классы и интерфейсы всегда описывают поведение, но факт заключается в том, что слишком часто они действительно просто описывают данные. Только вчера я смотрел видео о том, как кто-то строит так называемый BankAccountкласс, который был не чем иным, как прославленным int(действительно, он был гораздо менее полезен, чем класс int, таким образом, «убивая» повторное использование, которое я бы имел, если бы его просто оставили как int), все во имя «хорошего» дизайна. Количество кода, пота и слез, потраченных на постоянное переизобретение запутанных представлений данных, просто поражает; если вы не используете данные осмысленным образом, тогда, пожалуйста, оставьте это.

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

CurtainDog
источник
Что вы подразумеваете под открываемостью? Это похоже на это ?
1
Да, я думаю, что это затрагивает много основных моментов. Это тонкий момент, но обнаружение - это уравновешивающее действие, делать слишком прозрачные вещи также нежелательно, потому что вы получите плохое отношение сигнал / шум.
CurtainDog