ООП против функционального программирования против процедурного

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

Примеры архитектуры приветствуются!


person Community    schedule 16.02.2009    source источник
comment
Это не полный ответ, но я немного напишу о том, как функциональность влияет / контрастирует на стиль OO (в контексте F #) здесь: lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511.entry   -  person Brian    schedule 16.02.2009
comment
Вы можете прочитать это! много примеров того, когда использовать какой муравей, какие основные отличия, плюсы / минусы и т. д.   -  person Nikita Ignatov    schedule 16.02.2009
comment
См. также: stackoverflow.com/questions/1530868   -  person dreftymac    schedule 04.03.2017
comment
Дядя Боб написал об этом в Твиттере. А также здесь.   -  person jaco0646    schedule 17.03.2020


Ответы (7)


Все они хороши по-своему - просто разные подходы к одним и тем же проблемам.

В чисто процедурном стиле данные, как правило, сильно отделены от функций, которые с ними работают.

В объектно-ориентированном стиле данные имеют тенденцию нести с собой набор функций.

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

Конечно, сам язык влияет только на то, какой стиль предпочтительнее. Даже на чисто функциональном языке, таком как Haskell, вы можете писать в процедурном стиле (хотя это крайне не рекомендуется), и даже на процедурном языке, таком как C, вы можете программировать в объектно-ориентированном стиле (например, в GTK + и EFL API).

Чтобы было ясно, «преимущество» каждой парадигмы заключается просто в моделировании ваших алгоритмов и структур данных. Если, например, ваш алгоритм включает списки и деревья, наиболее разумным может оказаться функциональный алгоритм. Или, если, например, ваши данные сильно структурированы, может иметь смысл составить их как объекты, если это естественная парадигма вашего языка, - или это может быть так же легко написано как функциональная абстракция монад, которая это родная парадигма таких языков, как Haskell или ML.

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

person greyfade    schedule 16.02.2009
comment
То, что вы сказали, похоже, не отражает того, что вы написали. Вы говорите, что у них нет «за» и «против», а затем говорите, что у них разные подходы. Почему кто-то предпочел бы один подход другому в зависимости от конкретной ситуации? сильные и слабые стороны, плюсы и минусы, как бы вы их ни называли, они действительно существуют! Я не говорю, что один по своей сути лучше, и вы тоже. Я считаю, что это то, что вы действительно пытались сказать. если вы действительно не верите, что какой-либо выбранный подход не имеет положительных и отрицательных сторон по сравнению с другим подходом. - person J. M. Becker; 19.10.2011
comment
@TechZilla: Я согласен, что моя формулировка была плохой, но я имел в виду, что на самом деле нет списка функций, на которые вы могли бы указать и сказать, что язык X лучше, чем Y, без уточнения того, что язык X лучше подходит для написания алгоритма U и языка Y может лучше подходить для написания алгоритма V, в то время как оба могут быть легко реализованы на любом языке. - person greyfade; 19.10.2011
comment
Мне непонятна разница между процедурным и функциональным. Я изучаю Scheme / Rackett в колледже, но я действительно не вижу большой разницы между этим и процедурным C или PHP, не могли бы вы привести какой-нибудь пример? - person Leonel; 01.04.2012
comment
@Leonel: Самая большая разница, на которую будет ссылаться большинство людей, заключается в том, что в процедурных языках вы можете использовать цикл for, но в функциональных языках такой вещи нет - вместо этого вы используете рекурсивные вызовы функций для выполнения той же задачи. Функциональные языки также делают функции первоклассными объектами - вы можете передавать их, как числа, - но вы не можете этого сделать в C (а поддержка PHP для этого нарушена). - person greyfade; 24.04.2012
comment
Было бы неплохо, если бы вы могли перечислить некоторые преимущества одного метода перед другим. - person Jo Smo; 13.07.2014
comment
@tastro: Это совершенно неправильный вопрос. Никаких преимуществ, как таковых. Каждая языковая парадигма просто предлагает отличный от других набор абстракций. - person greyfade; 13.07.2014
comment
@greyfade хорошо, позвольте мне перефразировать: когда одно лучше, а когда другое? - person Jo Smo; 13.07.2014
comment
@tastro: Когда одна парадигма имеет больше смысла, чем другая. Вот и все. Иногда имеет смысл моделировать ваш код как композицию функций, а иногда имеет смысл моделировать ваши данные как объекты. Есть много способов выразить алгоритмы и структуры данных. ООП и функциональность - две из этих вещей. - person greyfade; 14.07.2014
comment
@TechZilla, пожалуйста, поймите, что это объяснение очень подробное и дает вам истинное определение между различными парадигмами. Поймите, что плюсы и минусы различаются в зависимости от разработчика / программиста, предполагаемых целей, языка и т. Д. Я предлагаю, если вы ищете плюсы и минусы, возьмите эти определения и оцените их в соответствии с вашей задачей, а затем проанализируйте свои результаты на плюсы и минусы. - person Ryan Watts; 30.07.2014
comment
Для протокола, я возражаю против использования аргументов «за» и «против» или фразы «каждый по-своему хорош» как бессвязной чепухи. Эти подходы к программированию - просто разные парадигмы в прямом смысле этого слова. Я бы отредактировал свой ответ, чтобы удалить нецензурную лексику, за исключением того, что люди, кажется, цепляются за эту ерунду. - person greyfade; 22.01.2019

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

Например, если вы создаете видеоигру, на C ++ есть больше хороших примеров кода и SDK, так что вам, вероятно, будет лучше. Для небольшого веб-приложения есть несколько отличных фреймворков Python, PHP и Ruby, которые помогут вам быстро начать работу. Java - отличный выбор для больших проектов из-за проверки во время компиляции и корпоративных библиотек и платформ.

Раньше стандартные библиотеки для разных языков были довольно маленькими и легко воспроизводились - C, C ++, Assembler, ML, LISP и т. Д. Поставлялись с основами, но имели тенденцию отклоняться, когда дело доходило до стандартизации. такие как сетевая связь, шифрование, графика, форматы файлов данных (включая XML), даже базовые структуры данных, такие как сбалансированные деревья и хэш-таблицы, были исключены!

Современные языки, такие как Python, PHP, Ruby и Java, теперь поставляются с гораздо более приличной стандартной библиотекой и имеют много хороших сторонних библиотек, которые вы можете легко использовать, во многом благодаря их принятию пространств имен, чтобы библиотеки не конфликтовали друг с другом. и сборка мусора для стандартизации схем управления памятью библиотек.

person Community    schedule 16.02.2009
comment
Python, ruby, ... не имеют стандартных библиотек, таких как C или LISP, поскольку они являются едиными языками реализации. Python - это то, что говорит Гвидо, стандарта нет. Любая конкретная реализация C или LISP (или чего-то еще) в настоящее время поставляется с большим набором библиотек, помимо стандартных. - person Dan Andreatta; 13.05.2010
comment
Вопрос касался различий между объектно-ориентированным, функциональным и процедурным программированием. Хотя языки, упомянутые в этих ответах, безусловно, поддаются одному из этих подходов, в ответе не упоминается ни одна из этих концепций ... Независимо от того, [...] [преобладают ли доступные библиотеки] над парадигмой, это не так. Я не отвечаю на поставленный вопрос, тем самым уклоняясь от того, что является полностью правильным вопросом. - person rinogo; 26.10.2013
comment
Напыщенная речь ircmaxell: blog.ircmaxell.com/2012/07/ oop-vs-procdural-code.html - person rinogo; 26.10.2013

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

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

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

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

То же самое и с ООП. Такой язык, как Java, не позволяет писать процедуры / функции вне класса. Единственный способ передать функцию - обернуть ее в объект, реализующий эту функцию, а затем передать этот объект.

В Python этого ограничения нет.

person Community    schedule 17.02.2009
comment
Я полагаю, вы имели в виду, что эти парадигмы не должны быть взаимоисключающими. Три из них являются ортогональными в том смысле, что в идеале вы можете использовать один, два или три из них в одной программе (если ваш язык позволяет это). - person Joe Pineda; 19.02.2009
comment
Да, я думаю, взаимоисключающие - лучший термин для этого! Благодарность - person hasen; 19.02.2009

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

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

person panschk    schedule 16.02.2009
comment
Есть соблазн проголосовать против за увековечивание неправильного представления о том, что Object = GUI widget, но я воздержусь. ООП работает так же хорошо для представления абстрактных понятий, как UserAccount или PendingSale, так и для видимых элементов интерфейса, таких как Window и Button. - person Dave Sherohman; 16.02.2009
comment
Я писал, что окно может быть объектом. Как вы сделаете вывод, что каждый объект - это окно? Это был просто пример. Конечно, ООП также можно использовать для моделирования абстрактных сущностей и их взаимосвязей. В любом случае, спасибо, что не проголосовали против. В любом случае у меня мало очков: D - person panschk; 16.02.2009
comment
-1. ООП не имеет ничего общего с графическим интерфейсом пользователя. В идеале лучший способ создания графического интерфейса - использование внешнего текстового файла (например, HTML). В то время как такие вещи, как обработка строк, на самом деле намного лучше выполняются с помощью объектов. (подумайте о струнах в C) !! - person hasen; 17.02.2009
comment
Не знаю, может, я просто привык к программированию с объектами, чтобы это реализовать. Но как бы вы могли сделать некоторые интерактивные вещи, например, изменить значение в TextBox X, если значение TextBox Y было изменено без использования объектов? Хорошо, вы можете просто использовать глобальные переменные для всего ... - person panschk; 18.02.2009
comment
Строки можно довольно легко обрабатывать в Perl и PHP без использования ООП. Но ладно, возможно, я выбрал не лучший пример. Я хотел сказать, что разные парадигмы полезны для разных задач. - person panschk; 18.02.2009
comment
Обработка строк великолепно выполняется в Perl (в 100 раз лучше, чем в Java, C ++ или C #), но строковые функции языка абсолютно НЕ объектно-ориентированы. Обработка строк в C была ужасной, но C - не единственный (и не лучший) процедурный язык. - person Joe Pineda; 19.02.2009
comment
+1 за Вы можете писать функциональные, процедурные или объектно-ориентированные практически на любом популярном языке, хотя для некоторых это может потребовать дополнительных усилий. Однако я не обязательно согласен с остальной частью ответа. - person Zsolt Török; 28.01.2011
comment
Вы можете писать в функциональном стиле практически на любом языке, но мне трудно понять, как выполнять стандартную повседневную функциональную работу на большинстве языков. Это круто, чтобы получить функторы в императивном коде. - person Fresheyeball; 12.09.2014
comment
›Но как бы вы сделали некоторые интерактивные вещи, например, изменение значения в TextBox X, если значение TextBox Y было изменено без использования объектов? Относитесь к ним как к ручьям. Вызвать поток событий изменения из x, применить какое-то преобразование, передать по конвейеру y: xEvents.map(someTransform).pipe(y) - person Eric Elliott; 11.12.2014

Чтобы ответить на ваш вопрос, нам понадобятся два элемента:

  1. Понимание характеристик различных архитектурных стилей / паттернов.
  2. Понимание характеристик различных парадигм программирования.

Список стилей / шаблонов архитектуры программного обеспечения показан в статье об архитектуре программного обеспечения на сайте Wikipeida. И вы можете легко найти их в Интернете.

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

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

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

person Gabriel Chung    schedule 16.02.2009

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

person Community    schedule 16.02.2009

Один из моих друзей пишет графическое приложение, используя NVIDIA CUDA. Приложение очень хорошо вписывается в парадигму ООП, и проблема может быть аккуратно разложена на модули. Однако для использования CUDA вам необходимо использовать C, который не поддерживает наследование. . Следовательно, нужно быть умным.

а) Вы разрабатываете умную систему, которая в определенной степени имитирует наследование. Это можно сделать!

i) Вы можете использовать систему ловушек, которая ожидает, что каждый дочерний элемент C родительского P будет иметь определенное переопределение для функции F. Вы можете заставить детей регистрировать свои переопределения, которые будут сохраняться и вызываться при необходимости.

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

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

б) Вы можете использовать последовательную политику именования и использовать подход разделяй и властвуй для создания программы. У него не будет никакого наследования, но поскольку ваши функции небольшие, легкие для понимания и единообразно отформатированы, они вам не нужны. Объем кода, который вам нужно написать, увеличивается, очень сложно оставаться сосредоточенным и не поддаваться легким решениям (хакам). Однако этот способ кодирования ниндзя - это способ кодирования C. Сохранение баланса между свободой на низком уровне и написанием хорошего кода. Хороший способ добиться этого - написать прототипы с использованием функционального языка. Например, Haskell очень хорош для создания прототипов алгоритмов.

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

person Community    schedule 20.02.2009
comment
Первые коппилеры C ++ были не чем иным, как препроцессорами, которые генерировали код C. Таким образом, ВСЕ функции C ++, включая множественное наследование, могут быть реализованы с использованием C. (для эмуляции обработки исключений C ++ в C потребуется некоторая поддержка платформы для исключений, но реализации C ++ также требуют этого, поэтому я не думаю, что это делает базовый идея недействительна). - person Chris Becke; 23.05.2009
comment
@Chris Becke, ваш ответ слишком философский. Во-первых, C имеет несколько стандартов (на протяжении многих лет), и почти ни один из них не полностью принят компиляторами C, не говоря уже о C ++. Сказать, что C ++ является надмножеством C, потому что он использует синтаксис C, не имеет большого значения, потому что вы даже не можете написать код для одного компилятора C, который компилируется в другом компиляторе C без значительных усилий. Кроме того, существуют языковые функции (системы типов, поддержка OOD), предлагаемые на других языках, которые было бы невозможно реализовать на C без использования C для разработки нового языка (именно поэтому существуют «новые языки»). - person Sprague; 06.01.2011
comment
Знаешь. Я больше не вижу, какое отношение мой комментарий имеет к этому посту. :П - person Chris Becke; 06.01.2011
comment
Cuda уже некоторое время поддерживает C ++. - person Aryeh Leib Taurog; 02.03.2015