Функциональное программирование и объектно-ориентированное программирование [закрыто]

784

До сих пор я в основном знакомился с ОО-программированием и с нетерпением жду изучения функционального языка. Мои вопросы:

  • Когда вы выбираете функциональное программирование, а не объектно-ориентированное?
  • Каковы типичные определения проблем, где функциональное программирование является лучшим выбором?
Olivier Lalonde
источник
Дубликат: stackoverflow.com/questions/552336/...
gnovice
это уместно programmers.stackexchange.com/questions/9730/…
kirill_igum
1
Подобный вопрос cs.se также закрыл то, что является примером, где функциональное программирование дает лучшие результаты, чем императивный стиль . общепринятым кажется, что одно не превосходит другого, или они не сопоставимы по простым критериям, или что они используются для различных целей ... функциональное программирование имеет больше научных / академических корней и использования и менее распространено в промышленности Таким образом, этот вопрос также создает неразрешимый конфликт интересов между «индустрией и академией». одна классическая ссылка, которая показывает ООП sytle в функциональном программировании, книга
SICP
« OO делает код понятным за счет инкапсуляции движущихся частей. FP делает код понятным за счет минимизации движущихся частей». - Micheal Feathers, 2010
jaco0646

Ответы:

1193

Когда вы выбираете функциональное программирование, а не объектно-ориентированное?

Когда вы ожидаете другой вид эволюции программного обеспечения:

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

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

Когда эволюция идет не так, у вас есть проблемы:

  • Добавление новой операции в объектно-ориентированную программу может потребовать редактирования многих определений классов для добавления нового метода.

  • Добавление нового вида вещей в функциональную программу может потребовать редактирования многих определений функций для добавления нового случая.

Эта проблема была хорошо известна в течение многих лет; в 1998 году Фил Вадлер назвал это «проблемой самовыражения» . Хотя некоторые исследователи считают, что проблему выражения можно решить с помощью таких языковых функций, как миксины, широко распространенное решение еще не достигло широкого распространения.

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

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

Norman Ramsey
источник
119
За этим ответом стоит серьезный дзен. Я думаю, что это освещает тот факт, что определенные шаблоны проектирования ООП (Visitor) на самом деле являются хаки, которые пытаются преодолеть проблему добавления новых операций.
Jacobs Data Solutions
54
В JavaScript вы можете иметь все вещи.
Эрик Реппен
61
@ErikReppen, в какой момент возникает вопрос, когда вы решите использовать функциональные возможности и когда вы решите использовать объектно-ориентированные функции?
Норман Рэмси
7
@NormanRamsey Совсем нередко смешивать его в JS, а первоклассные функции связаны со многими функциями, связанными с JS OOP. Сортировка массива JS принимает функции в качестве аргумента, который может создавать некоторые мощные структуры данных. Замыкания + переданная функция используется для того, чтобы объекты jquery были очень легкими в памяти, поскольку большинство методов являются просто ссылками. И т.д ...
Эрик Реппен
9
@NormanRamsey: Очень хороший ответ, в соответствии с SICP. Согласно этой классификации, функциональное и процедурное программирование группируются на противоположной стороне объектно-ориентированного программирования. Это может объяснить бум ООП в конце 1980-х - начале 1990-х годов: когда графические интерфейсы стали общепринятыми, ООП оказалось хорошим подходом для их моделирования, поскольку обычно у вас есть фиксированный набор операций (рисование, открытие, закрытие, изменение размера) и растущее количество виджетов. Конечно, это не означает, что ООП лучше, чем процедурное для любого приложения, как вы показали.
Джорджио
177

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

Взять к примеру C #. Можно сказать, что это в основном ООП, но есть много концепций и конструкций FP. Если вы рассматриваете Linq , наиболее важные конструкции, которые позволяют Linq существовать, функциональны по своей природе: лямбда-выражения .

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

Многие современные языки мультипарадигмы.

Рекомендуемые показания

Поскольку я нахожусь в одной лодке (фон ООП, изучаю FP), я бы посоветовал вам некоторые чтения, которые я действительно ценю:

Bruno Reis
источник
8
@duffymo: ваш комментарий, как вы это выразили, в основном бессмысленен. Никто не хочет сравнения языков, виртуальных машин или платформ, спасибо.
Бруно Рейс
6
@Bruno - ответ на «мощь .NET». Расслабьтесь.
duffymo
6
Забавно, я не вижу, как ты упрекаешь Дикама за его бессмысленные комментарии. Вы были назначены модератором, а я не смотрел? Никто не пылает здесь, кроме вас. Я скажу это снова - расслабься.
duffymo
4
Хех, извини, если я начал гореть. Я не хотел сказать, что другие платформы менее мощные, просто .NET поддерживает не только ООП. Например, у него есть оптимизация хвостового вызова.
Dykam
5
@nawfal, пока вы не сможете указать на некоторые внутренние особенности двух парадигм и сказать, что они несовместимы, они ортогональны: это сердце дискуссии. FP по определению несовместим с императивным программированием, но ООП не ограничивается императивным программированием. Причина, по которой у нас есть разные слова для этих понятий, заключается в том, что мы можем говорить о них: когда вы смешиваете их вместе, вы просто заставляете нас без необходимости придумывать новые слова.
DavidS
31

Объектно-ориентированное программирование предлагает:

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

Функциональное программирование в Haskell или даже в Scala может позволить замену через более общий механизм классов типов. Изменчивое внутреннее состояние либо не рекомендуется, либо запрещено. Инкапсуляция внутреннего представления также может быть достигнута. См Хаскелл против ООП для хорошего сравнения.

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

EDITED Удалена ссылка на неявные преобразования при обсуждении классов типов. В Scala классы типов кодируются с неявными параметрами, а не с преобразованиями, хотя неявные преобразования являются еще одним средством достижения замены совместимых типов.

ретроним
источник
3
Классы типов не являются механизмом неявного преобразования в другие типы. Это описание набора функций, определенных для типа, чтобы обеспечить форму полиморфизма. Наиболее близкой вещью из ООП в стиле Java были бы интерфейсы, хотя классы типов Haskell имеют некоторые важные различия.
Зак
25
  1. Если вы находитесь в сильно параллельной среде, тогда полезно чисто функциональное программирование. Отсутствие изменяемого состояния делает параллелизм почти тривиальным. Смотри Эрланг.

  2. В мультипарадигмальном языке вы можете захотеть смоделировать некоторые вещи функционально, если наличие изменяемого состояния должно быть деталью реализации, и, следовательно, FP - хорошая модель для проблемной области. Например, смотрите список представлений в Python или std.range на языке программирования D. Они вдохновлены функциональным программированием.

dsimcha
источник