Функциональное программирование против объектно-ориентированного программирования
До сих пор я в основном знакомился с ОО-программированием и с нетерпением жду изучения функционального языка. Мои вопросы:
- Когда вы выбираете функциональное программирование, а не объектно-ориентированное?
- Каковы типичные определения проблем, где функциональное программирование является лучшим выбором?
4 ответа
Когда вы выбираете функциональное программирование, а не объектно-ориентированное?
Когда вы ожидаете другой вид эволюции программного обеспечения:
Объектно-ориентированные языки хороши, когда у вас есть фиксированный набор операций над вещами, и когда ваш код развивается, вы в первую очередь добавляете новые вещи. Это может быть достигнуто путем добавления новых классов, которые реализуют существующие методы, и существующие классы остаются одни.
Функциональные языки хороши, когда у вас есть фиксированный набор вещей, и когда ваш код развивается, вы в первую очередь добавляете новые операции над существующими вещами. Это может быть достигнуто путем добавления новых функций, которые вычисляются с существующими типами данных, и существующие функции остаются в покое.
Когда эволюция идет не так, у вас есть проблемы:
Добавление новой операции в объектно-ориентированную программу может потребовать редактирования многих определений классов для добавления нового метода.
Добавление нового вида вещей в функциональную программу может потребовать редактирования многих определений функций для добавления нового случая.
Эта проблема была хорошо известна в течение многих лет; в 1998 году Фил Вадлер назвал это "проблемой выражения". Хотя некоторые исследователи считают, что проблему выражения можно решить с помощью таких языковых функций, как миксины, широко распространенное решение еще не достигло широкого распространения.
Каковы типичные определения проблем, где функциональное программирование является лучшим выбором?
Функциональные языки превосходно работают с символическими данными в древовидной форме. Любимый пример - это компиляторы, где исходные и промежуточные языки меняются редко (в основном это одно и то же), но авторы компиляторов всегда добавляют новые переводы и улучшения или оптимизации кода (новые операции над вещами). Компиляция и перевод в более общем смысле являются "убийственными приложениями" для функциональных языков.
Вам не обязательно выбирать между двумя парадигмами. Вы можете написать программное обеспечение с ОО-архитектурой, используя множество функциональных концепций. FP и OOP имеют ортогональный характер.
Взять к примеру C#. Можно сказать, что это в основном ООП, но существует множество концепций и конструкций FP. Если вы рассматриваете Linq, наиболее важные конструкции, которые позволяют Linq существовать, являются функциональными по своей природе: лямбда-выражения.
Другой пример, F#. Можно сказать, что это в основном FP, но есть много концепций и конструкций ООП. Вы можете определять классы, абстрактные классы, интерфейсы, иметь дело с наследованием. Вы даже можете использовать изменчивость, когда это делает ваш код более понятным или когда это значительно повышает производительность.
Многие современные языки мультипарадигмы.
Рекомендуемые показания
Так как я нахожусь в одной лодке (фон ООП, изучаю ФП), я бы предложил вам несколько чтений, которые мне очень понравились:
Функциональное программирование для повседневной разработки.NET, Джереми Миллер. Отличная статья (хотя и в плохо отформатированном виде), показывающая множество методов и практических реальных примеров FP на C#.
Функциональное программирование в реальном мире, Томас Петричек. Отличная книга, посвященная главным образом концепциям FP, пытающаяся объяснить, что они из себя представляют, когда их следует использовать. Есть много примеров как в F#, так и в C#. Кроме того, блог Petricek является отличным источником информации.
Объектно-ориентированное программирование предлагает:
- Инкапсуляция, чтобы
- контролировать мутацию внутреннего состояния
- предельная связь с внутренним представлением
- Подтип, позволяющий:
- замещение совместимых типов (полиморфизм)
- грубое средство разделения реализации между классами (наследование реализации)
Функциональное программирование в Haskell или даже в Scala может позволить замену через более общий механизм классов типов. Изменчивое внутреннее состояние либо не рекомендуется, либо запрещено. Инкапсуляция внутреннего представления также может быть достигнута. Смотрите Haskell против ООП для хорошего сравнения.
Утверждение Нормана о том, что "Добавление нового вида вещей в функциональную программу может потребовать редактирования многих определений функций для добавления нового случая". зависит от того, насколько хорошо функциональный код использует классы типов. Если сопоставление с образцом для определенного абстрактного типа данных распространяется по всей базе кода, вы действительно будете страдать от этой проблемы, но, возможно, это плохой дизайн для начала.
EDITED Удалена ссылка на неявные преобразования при обсуждении классов типов. В Scala классы типов кодируются с неявными параметрами, а не с преобразованиями, хотя неявные преобразования являются еще одним средством достижения замены совместимых типов.
Если вы находитесь в сильно параллельной среде, тогда полезно чисто функциональное программирование. Отсутствие изменяемого состояния делает параллелизм почти тривиальным. Смотри Эрланг.
В мультипарадигмальном языке вы можете захотеть смоделировать некоторые вещи функционально, если наличие изменяемого состояния должно быть деталью реализации, и, следовательно, FP - хорошая модель для проблемной области. Например, см. Список представлений в Python или std.range на языке программирования D. Они вдохновлены функциональным программированием.
Объектно-ориентированное программирование (ООП) - это парадигма программирования, основанная на концепции "объектов", которые представляют собой структуры данных, которые содержат данные в форме полей, часто называемых атрибутами; и код в форме процедур, часто называемых методами.
Функциональное программирование - это парадигма программирования, стиль построения структуры и элементов компьютерных программ, который рассматривает вычисления как оценку математических функций и избегает изменяющихся состояний и изменчивых данных.
ООП говорит, что объединение данных и их поведения в одном месте облегчает понимание того, как работает программа. ФП говорит, что данные и поведение являются совершенно разными вещами и должны быть разделены для ясности.
Даже сочетание как Javascript, так и объектно-ориентированного программирования позволяет разработчикам писать чистые, лаконичные и воспроизводимые коды. Разработчики могут создавать небольшие блоки кода, которые затем можно будет вызывать снова, без необходимости переписывать код или копировать и вставлять код снова и снова. ООП JavaScript также предлагает наследование на основе прототипов, а не на основе классов, что позволяет объектам напрямую наследовать от других объектов.