Заменяет ли функциональное программирование шаблоны проектирования GoF? - PullRequest
1012 голосов
/ 29 ноября 2008

С тех пор как я начал изучать F # и OCaml в прошлом году, я прочитал огромное количество статей, в которых утверждается, что шаблоны проектирования (особенно в Java) - это обходные пути для отсутствующих функций в императивных языках. Одна статья, которую я нашел , выдвигает довольно сильные претензии :

Большинство людей, которых я встречал, читали Книга «Шаблоны дизайна» от банды Четыре. Любой уважающий себя программист скажу вам, что книга языковая независимость и закономерности применить к разработке программного обеспечения в вообще, независимо от того, на каком языке ты используешь. Это благородное требование. К сожалению, это далеко от правда.

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

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

Кроме того, на функциональных языках, которые поддерживают ООП (таких как F # и OCaml), мне кажется очевидным, что программисты, использующие эти языки, будут использовать те же шаблоны проектирования, которые доступны для любого другого языка ООП. Фактически, сейчас я использую F # и OCaml каждый день, и нет никаких разительных отличий между шаблонами, которые я использую в этих языках, и шаблонами, которые я использую, когда пишу в Java.

Есть ли правда в утверждении, что функциональное программирование устраняет необходимость в шаблонах проектирования ООП? Если да, не могли бы вы опубликовать или дать ссылку на пример типового шаблона ООП и его функциональный эквивалент?

Ответы [ 24 ]

1031 голосов
/ 30 ноября 2008

Сообщение в блоге, которое вы цитировали, немного преувеличивает его утверждение. FP не исключает необходимость в шаблонах проектирования. Термин «шаблоны проектирования» просто широко не используется для описания того же в языках FP. Но они существуют. Функциональные языки имеют множество правил наилучшей практики в форме «когда вы сталкиваетесь с проблемой X, используйте код, похожий на Y», что в основном и является шаблоном проектирования.

Тем не менее, верно, что большинство специфичных для ООП шаблонов проектирования в функциональных языках практически не имеют значения.

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

Вот что говорит Банда Четырех по этому вопросу:

Выбор языка программирования важен, потому что он влияет на точку зрения. Наши шаблоны предполагают особенности языка уровня Smalltalk / C ++, и этот выбор определяет, что можно, а что нельзя легко реализовать. Если бы мы предполагали процедурные языки, мы могли бы включить шаблоны проектирования, называемые «Наследование», «Инкапсуляция» и «Полиморфизм». Точно так же некоторые из наших шаблонов поддерживаются непосредственно менее распространенными объектно-ориентированными языками. Например, CLOS имеет несколько методов, которые уменьшают потребность в шаблоне, таком как Visitor. На самом деле, между Smalltalk и C ++ достаточно различий, чтобы означать, что некоторые шаблоны могут быть выражены легче на одном языке, чем на другом. (См. Итератор, например.)

(Выше приведена цитата из книги «Введение в шаблоны проектирования», стр. 4, абзац 3)

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

Что такое шаблон команды, если не приближение функций первого класса? :) На языке FP вы просто передаете функцию в качестве аргумента другой функции. В языке ООП вы должны заключить функцию в класс, который вы можете создать, а затем передать этот объект другой функции. Эффект тот же, но в ООП он называется шаблоном проектирования и требует намного больше кода. А что такое абстрактный шаблон фабрики, если не карри? Поочередно передавайте параметры функции, чтобы настроить, какое значение она выдает, когда вы, наконец, вызываете ее.

Так что да, некоторые шаблоны проектирования GoF отображаются избыточными в языках FP, поскольку существуют более мощные и простые в использовании альтернативы.

Но, конечно, есть еще шаблоны проектирования, которые не решаются языками FP. Что такое эквивалент FP синглтона? (На мгновение не обращая внимания на то, что использование синглетонов - это, как правило, ужасный шаблон)

И это работает в обе стороны. Как я уже сказал, у FP тоже есть свои шаблоны проектирования, люди просто не думают о них как таковые.

Но вы могли наткнуться на монады. Каковы они, если не шаблон дизайна для "работы с глобальным состоянием"? Эта проблема настолько проста в языках ООП, что там не существует эквивалентного шаблона проектирования.

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

Говорить, что Монада - это шаблон проектирования, так же абсурдно, как и говорить, что целые числа с их обычными операциями, а нулевой элемент - это шаблон проектирования. Нет, монада - это математический паттерн , а не паттерн проектирования.

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

Дополнительно на функциональных языках которые поддерживают ООП (такие как F # и OCaml), мне кажется очевидным, что программисты, использующие эти языки будет использовать те же шаблоны дизайна найден доступным для каждого ООП язык. На самом деле, сейчас я использую F # и OCaml каждый день, и нет разительные различия между шаблоны, которые я использую в этих языках против шаблоны, которые я использую, когда пишу в Java.

Возможно, потому что ты все еще думаешь настоятельно? Многие люди, всю жизнь имея дело с императивными языками, с трудом отказываются от этой привычки, когда пытаются использовать функциональный язык. (Я видел несколько довольно забавных попыток в F #, где буквально каждая функция была просто строкой операторов 'let', в основном, как если бы вы взяли программу на C и заменили все точки с запятой на 'let '.:))

Но другая возможность может заключаться в том, что вы просто не поняли, что решаете проблемы тривиально, для чего потребуются шаблоны проектирования на языке ООП.

Когда вы используете каррирование или передаете функцию в качестве аргумента другой, остановитесь и подумайте, как бы вы сделали это на языке ООП.

Есть ли правда в утверждении, что функциональное программирование устраняет нужен для шаблонов проектирования ООП?

Да. :) Когда вы работаете на языке FP, вам больше не нужны специфичные для ООП шаблоны проектирования. Но вам все еще нужны некоторые общие шаблоны проектирования, такие как MVC или другие, не относящиеся к ООП, вещи, и вместо этого вам понадобится пара новых специфических для FP «шаблонов проектирования». У всех языков есть свои недостатки, и шаблоны проектирования обычно таковы, как мы их обходим.

В любом случае, вам может быть интересно попробовать свои силы в «более чистых» языках FP, таких как ML (мой личный фаворит, по крайней мере, в учебных целях) или Haskell, где у вас нет опоры OOP, чтобы отступить когда вы сталкиваетесь с чем-то новым.


Как и ожидалось, несколько человек возразили против моего определения шаблонов проектирования как «исправление недостатков в языке», поэтому вот мое оправдание: Как уже говорилось, большинство шаблонов проектирования специфичны для одной парадигмы программирования, а иногда даже для одного конкретного языка. Часто они решают проблемы, которые существуют только в этой парадигме (см. Монады для FP или абстрактные фабрики для ООП). Почему абстрактный шаблон фабрики не существует в FP? Потому что проблемы, которую он пытается решить, там не существует. Таким образом, если существует проблема в языках ООП, которой нет в языках FP, то ясно, что это недостаток языков ООП. Проблема может быть решена, но ваш язык этого не делает, но для ее решения вам понадобится куча шаблонного кода. В идеале, мы бы хотели, чтобы наш язык программирования волшебным образом устранял все проблемы. Любая проблема, которая все еще существует, в принципе является недостатком языка. ;)

146 голосов
/ 29 ноября 2008

Есть ли правда в утверждении, что функциональное программирование устраняет необходимость в шаблонах проектирования ООП?

Функциональное программирование отличается от объектно-ориентированного программирования. Объектно-ориентированные шаблоны проектирования не применимы к функциональному программированию. Вместо этого у вас есть шаблоны проектирования функционального программирования.

Для функционального программирования вы не будете читать книги шаблонов проектирования ОО, вы будете читать другие книги по шаблонам проектирования ФП.

языковая независимость

Не совсем. Только не зависит от языка в отношении ОО языков. Шаблоны проектирования вообще не применяются к процедурным языкам. Они едва имеют смысл в контексте проектирования реляционных баз данных. Они не применяются при разработке электронных таблиц.

типичный шаблон проектирования ООП и его функциональный эквивалент?

Выше не должно существовать. Это все равно что запросить часть процедурного кода, переписанного в виде ОО-кода. Хммм ... Если я перевожу оригинальный Фортран (или С) на Java, я ничего не сделал, кроме как перевести его. Если я полностью переписываю его в парадигму ОО, он больше не будет выглядеть как оригинальный Фортран или С - он будет неузнаваем.

Нет простого отображения между ОО-дизайном и Функциональным дизайном. Это очень разные взгляды на проблему.

Функциональное программирование (как все стили программирования) имеет шаблоны проектирования. Реляционные базы данных имеют шаблоны проектирования, ОО - шаблоны проектирования, процедурное программирование - шаблоны проектирования. У всего есть образцы дизайна, даже архитектура зданий.

Шаблоны проектирования - как концепция - представляют собой вечный способ построения, независимо от технологии или предметной области. Однако конкретные шаблоны проектирования применяются к конкретным проблемным областям и технологиям.

Каждый, кто думает о том, что он делает, открывает шаблоны проектирования.

44 голосов
/ 01 января 2009

Комментарии Брайана о тесной связи между языком и паттерном, к сути,

Недостающая часть этого обсуждения - понятие идиомы. Книга Коплиена «Advanced C ++» оказала здесь огромное влияние. Задолго до того, как он обнаружил Кристофера Александра и Колонку без имени (и вы не можете разумно говорить о шаблонах, не читая Александра тоже), он говорил о важности овладения идиомой в истинном изучении языка. В качестве примера он использовал копирование строки в C, в то время как (* from ++ = * to ++); Вы можете рассматривать это как банду для отсутствующей языковой функции (или библиотечной функции), но на самом деле важно то, что это большая единица мысли или выражения, чем любая из ее частей.

Вот что пытаются сделать шаблоны и языки, чтобы позволить нам выразить свои намерения более кратко. Чем богаче единицы мысли, тем сложнее мысли, которые вы можете выразить. Обладая богатым общим словарным запасом в разных масштабах - от системной архитектуры до мелочей - позволяет нам вести более умные разговоры и мысли о том, что нам следует делать.

Мы также можем учиться как личности. В этом весь смысл упражнения. Каждый из нас может понять и использовать то, что никогда не сможет думать о себе. Языки, структуры, библиотеки, шаблоны, идиомы и т. Д. Имеют свое место в разделении интеллектуального богатства.

38 голосов
/ 24 ноября 2009

Книга GOF явно связана с ООП - название «Шаблоны проектирования - Элементы многократного использования» Объектно-ориентированное Программное обеспечение (выделено мое).

33 голосов
/ 29 ноября 2008

Проектирование шаблонов в динамическом программировании Питера Норвигга подробно освещает эту общую тему, хотя о «динамических» языках вместо «функциональных» (есть совпадение).

25 голосов
/ 19 октября 2012

Вот еще одна ссылка, обсуждающая эту тему: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

В своем блоге Эдвард описывает все 23 исходных паттерна GoF в терминах Haskell.

19 голосов
/ 30 ноября 2008

Когда вы попытаетесь взглянуть на это на уровне «шаблонов проектирования» (в целом) и «FP против ООП», ответы, которые вы найдете, будут в лучшем случае мутными.

Пройдите уровень еще глубже по обеим осям и рассмотрите конкретные шаблоны проектирования и определенные языковые особенности , и все станет яснее.

Так, например, некоторые конкретные шаблоны, такие как Посетитель , Стратегия , Команда и Наблюдатель определенно изменяются или исчезают, когда использование языка с алгебраическими типами данных и сопоставлением с образцом , замыкания , функции первого класса и т. д. Некоторые другие шаблоны из книги GoF по-прежнему «остаются», хотя.

В целом, я бы сказал, что со временем определенные паттерны удаляются новыми (или просто растущими в популярности) языковыми функциями. Это естественный курс языкового дизайна; поскольку языки становятся более высокоуровневыми, абстракции, которые раньше можно было вызывать только в книге с использованием примеров, теперь становятся приложениями определенной языковой функции или библиотеки.

(Помимо: вот недавний блог , который я написал, в котором есть другие ссылки на дополнительные обсуждения FP и шаблонов проектирования.)

16 голосов
/ 30 ноября 2008

Представление Norvig ссылается на анализ, который они сделали для всех шаблонов GoF, и они говорят, что 16 из 23 шаблонов имели более простые реализации на функциональных языках или были просто частью языка. Таким образом, предположительно, по крайней мере, семь из них были либо a) одинаково сложными, либо b) отсутствовали в языке. К сожалению для нас, они не перечислены!

Я думаю, что ясно, что большинство «творческих» или «структурных» шаблонов в GoF - это просто уловки, чтобы заставить системы примитивного типа в Java или C ++ делать то, что вы хотите. Но остальные заслуживают рассмотрения независимо от того, на каком языке вы программируете.

Один может быть прототипом; Хотя это фундаментальное понятие JavaScript, его нужно реализовывать с нуля на других языках.

Один из моих любимых шаблонов - это шаблон Null Object: представлять отсутствие чего-либо как объекта, который ничего не делает. Это может быть проще для моделирования на функциональном языке. Однако настоящим достижением является сдвиг в перспективе.

15 голосов
/ 16 декабря 2008

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

9 голосов
/ 30 ноября 2008

И даже решения OO Design Pattern зависят от языка. Шаблоны проектирования - это решение общих проблем, которые ваш язык программирования не решает за вас. В Java шаблон Singleton решает проблему «что-то одно» (упрощенное). В Scala у вас есть конструкция верхнего уровня под названием Object в дополнение к Class. Это ленивый экземпляр и есть только один. Вам не нужно использовать шаблон Singleton, чтобы получить Singleton. Это часть языка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...