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

237

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

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

Ашутош Сингх-MVP SharePoint
источник
Это не полный ответ, но я немного напишу о том, как «функционал» влияет / противопоставляет стиль «OO» (в контексте F #) здесь: lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511. запись
Брайан
Вы можете прочитать это! Есть много примеров того, когда использовать какой муравей, в чем главные отличия, плюсы / минусы и т. Д.
Никита Игнатов,
1
Смотрите также: stackoverflow.com/questions/1530868
dreftymac
Дядя Боб написал в Твиттере об этом. И здесь тоже .
jaco0646

Ответы:

129

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

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

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

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

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

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

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

greyfade
источник
5
То, что вы сказали, похоже, не отражает того, что вы написали. Вы говорите, что у них нет «плюсов и минусов», а потом говорите, насколько они разные подходы. Почему кто-то выбирает один подход, а не другой, основываясь на той или иной ситуации? сильные и слабые стороны, плюсы и минусы, как бы вы их ни называли, они существуют! Я не говорю, что кто-то лучше по своей природе, как и вы. Я считаю, что это то, что вы действительно пытались сказать. если вы действительно не верите, что у любого выбранного подхода нет положительных и отрицательных сторон по сравнению с другим подходом.
Дж. М. Беккер
1
@TechZilla: Я согласен, что моя формулировка была плохой, но я имел в виду, что на самом деле нет списка возможностей, на которые можно указать и сказать, что язык X лучше, чем Y, без определения того, что язык X лучше подходит для написания алгоритма U и языка Y может быть лучше подходит для написания алгоритма V, в то время как оба могут быть легко реализованы на любом языке.
Greyfade
2
Разница между процедурной и функциональной мне не ясна. Я изучаю Scheme / Rackett в колледже, но я действительно не вижу большой разницы между ним и процедурным C или PHP, не могли бы вы привести пример?
Леонель
7
@Leonel: Самое большое различие, которое большинство людей процитирует, состоит в том, что в процедурных языках вы можете использовать цикл for, но в функциональных языках такого нет: вместо этого вы используете рекурсивные вызовы функций для выполнения одной и той же задачи. Функциональные языки также делают функции первоклассными объектами - вы можете передавать их, как число, - но вы не можете сделать это в C (и поддержка PHP в этом нарушена).
Greyfade
2
@tastro: когда одна парадигма имеет больше смысла, чем другая. Это действительно все. Иногда имеет смысл моделировать ваш код как композицию функций, а иногда имеет смысл моделировать ваши данные как объекты. Есть много способов выразить алгоритмы и структуры данных. ООП и функционал - вот две из этих вещей.
Greyfade
25

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

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

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

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

DOBES
источник
5
Python, ruby, ... не имеют "стандартных" библиотек, таких как C или LISP, поскольку они являются отдельными языками реализации. Python - это то, что говорит Гвидо, стандарта нет. В настоящее время любая конкретная реализация на C или LISP (или что-то еще) поставляется с большим набором библиотек, помимо стандартных.
Дэн Андреатта
8
Речь шла о различиях между объектно-ориентированным, функциональным и процедурным программированием. Хотя языки, упомянутые в этих ответах, безусловно, пригодны для одного из этих подходов, в ответе не упоминается ни одно из этих понятий ... Независимо от того, являются ли "доступные библиотеки [...] [превзойти] парадигму", это не отвечает на поставленный вопрос, тем самым обходя стороной вопрос, который является полностью допустимым.
Риного
1
Рак, связанный с ircmaxell
rinogo
20

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

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

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

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

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

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

оборота Хасен Дж
источник
Я полагаю, вы имели в виду «эти парадигмы не должны быть взаимоисключающими». Три из них являются ортогональными, в идеале вы можете использовать один, два или три из них в одной программе (если ваш язык позволяет это).
Джо Пинеда
Да, я думаю, что взаимоисключающие это лучший термин для этого! спасибо
hasen
14

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

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

panschk
источник
17
Соблазн понизить голос за увековечку заблуждения, что "Object = GUI widget", но я воздержусь. ООП работает так же хорошо для представления абстрактных понятий, таких как «UserAccount» или «PendingSale», как и для видимых элементов интерфейса, таких как «Окно» и «Кнопка».
Дейв Шерохман
5
Я написал, что окно может быть объектом. Как вы делаете вывод, что каждый объект является окном оттуда? Это был просто пример. Конечно, ООП также может использоваться для моделирования абстрактных объектов и их отношений. В любом случае, спасибо, что не понизили голосование. В любом случае, у меня не так много очков: D
panschk 16.02.09
6
-1. ООП не имеет ничего общего с GUI. В идеале, лучший метод для проектирования guis - это использование внешнего текстового файла (например, HTML). Хотя такие вещи, как обработка строк, на самом деле гораздо лучше работают с объектами. (подумайте о строках в C) !!
hasen
1
Я не знаю, может быть, я просто привык программировать с объектами, чтобы понять это. Но как бы вы сделали некоторые интерактивные вещи, такие как изменение значения в TextBox X, когда значение TextBox Y было изменено без использования объектов? Хорошо, вы можете просто использовать глобальные переменные для всего ...
panschk
1
Строковая обработка великолепно выполняется в perl (в 100 раз лучше, чем в Java, C ++ или C #), однако строковая функциональность языка абсолютно НЕ объектно-ориентирована. Обработка строк в C была ужасной, но C не единственный процедурный язык (и не лучший).
Джо Пинеда
6

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

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

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

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

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

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

Габриэль Чунг
источник
2

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

Сванте
источник
1

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

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

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

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

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

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

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

снег
источник
Первые компиляторы c ++ были не более чем препроцессорами, которые генерировали C-код. Таким образом, ВСЕ возможности c ++, включая множественное наследование, могут быть реализованы с использованием C. (эмуляция обработки исключений c ++ в C потребует некоторой поддержки платформы для исключений, но реализации c ++ тоже требуют этого, поэтому я не думаю, что это делает основной идея недействительна).
Крис Бекке
2
@ Крис Бекке, твой ответ слишком философский. С одной стороны, C имеет несколько стандартов (на протяжении многих лет), едва ли любой из них полностью принят компиляторами C, не говоря уже о c ++. Сказать, что C ++ является надмножеством C, потому что он использует синтаксис C, не значит много, потому что вы даже не можете написать код для одного компилятора C, который компилируется в другой компилятор C без значительных усилий. Кроме того, существуют языковые функции (системы типов, поддержка OOD), предлагаемые на других языках, которые невозможно реализовать в C без использования C для разработки нового языка (именно поэтому существуют «новые языки»)
Sprague
Знаешь. Я больше не вижу, какое отношение мой комментарий имеет к этому сообщению вообще. : P
Крис Бекк
Cuda уже давно поддерживает C ++.
Арье Лейб Таурог