Заменяет ли функциональное программирование шаблоны проектирования GoF?

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

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

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

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

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

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

29 ответов

Решение

Сообщение в блоге, которое вы цитировали, немного переоценивает его утверждение. 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, где у вас нет костыля ООП, к которому можно прибегнуть, когда вы столкнулись с чем-то новым.


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Так, например, некоторые конкретные шаблоны, такие как Visitor, Strategy, Command и Observer, определенно изменяются или исчезают при использовании языка с алгебраическими типами данных и сопоставлением с образцами, замыканий, функций первого класса и т. Д. Некоторые другие шаблоны из книги GoF по-прежнему "держись вокруг", хотя.

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

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

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

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

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

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

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

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

Шаблоны - это способы решения похожих проблем, которые можно увидеть снова и снова, а затем описать и документировать. Так что нет, FP не собирается заменять шаблоны; тем не менее, FP может создавать новые шаблоны и делать некоторые текущие шаблоны "передового опыта" "устаревшими".

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

Посмотрите, как Scala избавляется от "шаблона синглтона": вы просто объявляете объект вместо класса. Еще одна особенность, сопоставление с образцом, помогает избежать грубости шаблона посетителя. Смотрите сравнение здесь: http://andymaleh.blogspot.com/2008/04/scalas-pattern-matching-visitor-pattern.html

А Scala, как и F#, представляет собой сочетание ОО-функционала. Я не знаю о F#, но он, вероятно, имеет такие особенности.

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

Еще одно наблюдение. Этот фрагмент кода реализует шаблон: это такая классика, и она настолько элементарна, что мы обычно не думаем о ней как о "шаблоне", но она точно такова:

for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }

В императивных языках, таких как Java и C#, принята функциональная конструкция для решения этой проблемы: "foreach".

Шаблоны GoF Design Patterns - это рецепты обходного пути для ОО-языков, которые являются потомками Simula 67, таких как Java и C++.

Большинство "недугов", с которыми сталкиваются шаблоны проектирования, вызваны:

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

Не существует ни одного из этих шаблонов проектирования, который не исчезнет в Common Lisp Object System, даже если решение структурировано по существу так же, как в соответствующем шаблоне проектирования. (Более того, эта объектная система предшествует книге GoF более чем на десятилетие. Common Lisp стал стандартом ANSI в том же году, когда эта книга была впервые опубликована.)

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

Конструкция и доступ без мутаций совместимы с функциональным программированием, и поэтому могут применяться шаблоны, связанные с абстрагированием доступа или конструированием: шаблоны, такие как Factory, Facade, Proxy, Decorator, Visitor.

С другой стороны, поведенческие паттерны, такие как State и Strategy, вероятно, не применяются напрямую в функциональных ООП, потому что в основе лежит мутация состояния. Это не значит, что они не применяются; возможно, они как-то применяются в сочетании с любыми доступными трюками для имитации изменяемого состояния.

Я хотел бы добавить пару превосходных, но несколько плотных работ Джереми Гиббона: "Шаблоны проектирования как программы общего типа для типов данных более высокого порядка" и "Суть шаблона Итератор" (оба доступны здесь: http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/).

Они оба описывают, как идиоматические функциональные конструкции покрывают ландшафт, который покрывается определенными шаблонами проектирования в других (объектно-ориентированных) настройках.

Вы не можете иметь эту дискуссию без воспитания систем типов.

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

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

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

Первое, что делают классы типов, это устраняет необходимость в синглетонах.

Вы могли бы пройти список 23 и устранить больше, но у меня нет времени прямо сейчас.

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

По сути, да!

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

Кроме того, эта http://c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures содержит таблицу перевода "шаблон / функция" и некоторые приятные обсуждения, если вы хотите копать.

Функциональное программирование не заменяет шаблоны проектирования. Дизайн моделей не подлежит замене.

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

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

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

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

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

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

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

В новой книге 2013 года под названием "Шаблоны функционального программирования - в Scala и Clojure" автор Michael.B. Линн делает приличную работу, сравнивая и обеспечивая замены во многих случаях для шаблонов GoF, а также обсуждает более новые функциональные шаблоны, такие как "хвостовая рекурсия", "запоминание", "ленивая последовательность" и т. Д.

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

Как говорится в принятом ответе, у ООП и ФП есть свои специфические закономерности.

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

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

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

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

Кроме того, я заметил, что в типичном языке FP, Haskell, есть нечто похожее на шаблоны GoF, но с другими именами. На мой взгляд, это говорит о том, что они были там, потому что есть некоторые общие проблемы, которые нужно решить на языках FP и OOP.

  • Монада трансформер и декоратор. Первый используется для добавления дополнительных способностей в существующую монаду, второй - для добавления дополнительных способностей к существующему объекту.

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

Принцип HOF означает, что функции могут быть переданы в качестве аргументов другим функциям. и функции могут возвращать значения.

Это так, поскольку функциональный PL высокого уровня (например, OCaml, с классами, модулями и т. Д.), Безусловно, заменяет императивные языки ООП по универсальности типов и мощности выражения. Абстракции не просачиваются, вы можете выразить большинство своих идей прямо в программе. Следовательно, да, он заменяет шаблоны проектирования, большинство из которых в любом случае до смешного упрощены по сравнению с функциональными шаблонами.

ООП и ФП преследуют разные цели, ООП стремится инкапсулировать сложности / движущиеся части программных компонентов, а ФП стремится минимизировать сложность и зависимости программных компонентов, однако эти 2 парадигмы не обязательно противоречат на 100% и могут применяться вместе, чтобы получить выгоду из обоих миров. Даже с языком, который изначально не поддерживает функциональное программирование, таким как C#, вы могли бы писать функциональный код, если вы понимаете принципы FP, также вы можете применять принципы ООП с использованием F#, если вы понимаете принципы, шаблоны и лучшие практики ООП. Вы сделаете правильный выбор в зависимости от ситуации и проблемы, которую вы пытаетесь решить, независимо от используемого вами языка программирования.

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

По моему опыту разработки на языке с несколькими парадигмами (Ruby), реализация FP хорошо работает в простых случаях, но там, где контекст более сложен, подход на основе GoF OOP больше подходит.

Подход FP не заменяет подход ООП, он дополняет его.

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

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

Я бы не использовал функциональный язык для написания пользовательского интерфейса, но один из ОО-языков, таких как C# или Java, облегчит эту работу. Если бы я писал функциональный язык, я бы не стал использовать OO Design Patterns.

Первостепенной характеристикой функционального программирования, IMHO, является то, что вы программируете только с помощью выражений - выражений внутри выражений внутри выражений, которые все оценивают до последнего, последнего выражения, которое "греет машину при оценке".

Первостепенная характеристика объектно-ориентированного программирования, IMHO, заключается в том, что вы программируете с объектами, которые имеют внутреннее состояние. У вас не может быть внутреннего состояния в чистых функциях - объектно-ориентированным языкам программирования нужны операторы, чтобы что-то происходило. (В функциональном программировании нет операторов.)

Вы сравниваете яблоки с апельсинами. Шаблоны объектно-ориентированного программирования не применимы к программированию функций, потому что функциональное программирование - это программирование с помощью выражений, а объектно-ориентированное программирование - это программирование с внутренним состоянием.

Соберитесь.

Многих будет раздражать мое заявление о замене шаблонов проектирования и опровержении SOLID и DRY. Я - никто. Тем не менее, я правильно смоделировал совместную (производственную) архитектуру и опубликовал правила построения процессов в Интернете вместе с кодом и научными данными на моем веб-сайте http://www.powersemantics.com/.

Мой аргумент состоит в том, что шаблоны проектирования пытаются достичь того, что в производстве называется "массовой настройкой", - формы процесса, в которой каждый шаг может быть изменен, перекомпонован и расширен. Вы можете думать о таких процессах как о некомпилированных скриптах. Я не собираюсь здесь повторять свои (онлайн) аргументы. Короче говоря, моя архитектура массовой настройки заменяет шаблоны проектирования, достигая такой гибкости без какой-либо запутанной семантики. Я был удивлен, что моя модель так хорошо работает, но то, как программисты пишут код, просто не держит свечи в том, как производство организует совместную работу.

  • Производство = каждый шаг взаимодействует с одним продуктом
  • ООП = каждый шаг взаимодействует с самим собой и другими модулями, передавая продукт от точки к точке, как бесполезные офисные работники

Эта архитектура никогда не требует рефакторинга. Также существуют правила, касающиеся централизации и распределения, которые влияют на сложность. Но чтобы ответить на ваш вопрос, функциональное программирование - это еще один набор семантики обработки, а не архитектура для массовых пользовательских процессов, где 1) исходная маршрутизация существует как (сценарий) документ, который владелец может переписать перед запуском, и 2) модули могут быть легко и динамически добавляется или удаляется.

Можно сказать, что ООП - это парадигма "жестко запрограммированного процесса", а шаблоны проектирования - способы избежать этой парадигмы. Но в этом вся суть массовой настройки. Шаблоны проектирования воплощают динамические процессы в виде беспорядочного жесткого кода. В этом нет смысла. Тот факт, что F# позволяет передавать функции в качестве параметра, означает, что как функциональные языки, так и языки ООП пытаются выполнить массовую настройку самостоятельно.

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

Позвольте привести пример неправильной предпосылки, которую вы заявляете.

Шаблон адаптера, который у нас есть в ООП в качестве адаптера варианта использования, например, в cleanarch и ddd, может быть реализован в Functional через монадную вариацию Option.

Вы их не заменяете, а трансформируете.

Другие вопросы по тегам