Сравнение функционального и императивного программирования
В этом разделе сравнивается и противопоставляется функциональное программирование с традиционным императивным (процедурным) программированием.
Сравнение функционального икомандного программирования
Принципы функционального программирования формулировались специально для поддержки чисто функционального подхода к решению проблем. Функциональное программирование является одной из форм декларативного программирования. В отличие от этого, большинство традиционных языков, в том числе такие языки объектно-ориентированного программирования (OOP), как C#, Visual Basic, C++ и Java, разрабатывались в основном для императивного (процедурного) программирования.
При императивном подходе разработчик пишет код, подробно определяющий шаги, которые должен выполнить компьютер для достижения цели. Такое программирование иногда называют алгоритмическим. В отличие от него, функциональный подход сводится к составлению решения задачи в виде набора функций, которые должны быть выполнены. Разработчик подробно определяет вход каждой функции и возвращаемые ею результаты. В следующей таблице описаны некоторые важные различия между этими двумя подходами.
Характеристика |
Императивный подход |
Функциональный подход |
---|---|---|
Основная направленность усилий программиста |
Способы выполнения (алгоритмы) задач и отслеживания изменений в их состоянии. |
Требуемые данные и преобразования. |
Изменения состояния |
Важно! |
Не существует. |
Порядок выполнения |
Важно! |
Низкая значимость. |
Управление основным потоком данных |
Циклы, условия и вызовы функций (методов). |
Вызовы функций, включая рекурсивные. |
Основная единица обработки |
Экземпляры структур или классов. |
Функции как полноценные объекты и коллекции данных. |
Безусловно, большинство языков программирования было разработано в целях поддержки определенных подходов к программированию, но многие языки общего назначения являются достаточно гибкими, чтобы поддерживать несколько подходов. Например, большинство языков, содержащих указатели на функции, могут использоваться для надежной поддержки функционального программирования. Более того, в C# 3.0 и Visual Basic 9.0 были специально добавлены языковые расширения, предназначенные для поддержки функционального программирования, в том числе лямбда-выражения и определения типов. Одной из форм декларативного, функционального программирования является технология LINQ.
Функциональное программирование с помощью XSLT
Многие разработчики XSLT знакомы с чисто функциональным подходом. Наиболее эффективный способ разработки таблицы стилей XSLT состоит в том, что каждый шаблон рассматривается как изолированное, составное преобразование. При этом совершенно не приходится задумываться над тем, в каком порядке должны проводиться вычисления. XSLT исключает побочные эффекты (если не считать того, что применение механизмов экранирования, предназначенных для выполнения процедурного кода, может приводить к получению результатов функций, не соответствующих определениям этих функций). Таким образом, XSLT является эффективным инструментом, но некоторые его характеристики не оптимальны. Например, программные конструкции приходится представлять на языке XML, в связи с чем объем кода становится довольно большим, поэтому его сопровождение затрудняется. Кроме того, в управлении потоком широко применяется рекурсия, что может привести к созданию трудночитаемого кода. Дополнительные сведения об XSLT см. в разделе Преобразования XSLT.
Тем не менее XSLT доказал свою полезность при чисто функциональном подходе для преобразования XML из одного вида в другой. Чисто функциональное программирование с помощью LINQ to XML во многом похоже на XSLT. Но программные конструкции, вводимые LINQ to XML в C# 3.0 и Visual Basic 9.0, позволяют писать чисто функциональные преобразования, более удобочитаемые и легко обслуживаемые, чем XSLT.
Преимущества чистых функций
Основная причина реализации функциональных преобразований в виде чистых функций заключается в том, что чистые функции являются компонуемыми, т. е. самодостаточными без сохранения состояния. Это дает ряд преимуществ, включая следующие.
Повышенная удобочитаемость и обслуживаемость. Это объясняется тем, что каждая функция разрабатывается для выполнения конкретных задач, определяемых аргументами. Функция не зависит от какого-либо внешнего состояния.
Упрощается разработка, основанная на ранее созданном коде. Код становится более приемлемым для оптимизации кода, поэтому легче реализовать изменения в проекте. Например, предположим, что в процессе написания сложного преобразования выясняется, что какой-то код повторяется несколько раз. Если оптимизация кода предусматривает преобразование в чистый метод, то полученный чистый метод можно вызывать в любое время, не беспокоясь о побочных эффектах.
Упрощаются тестирование и отладка. Чистые функции проще тестировать отдельно от основной части кода, поэтому можно написать проверочный код, в котором чистая функция вызывается с типичными значениями, допустимыми краевыми значениями и недопустимыми краевыми значениями.
Освоение нового подхода разработчиками объектно-ориентированных приложений
Традиционное объектно-ориентированное программирование (OOP) является таковым, что большинство разработчиков привыкает писать код в императивном (процедурном) стиле. Переходя к разработке в чисто функциональном стиле, они должны изменить свое мышление и подход к разработке.
Чтобы решить задачу, разработчики объектно-ориентированных приложений проектируют иерархии классов, добиваются правильной инкапсуляции и мыслят в терминах контрактов между классами. Для них первостепенное значение имеет обеспечение правильного поведения и состояния типов объектов, а для достижения этого используются такие возможности языка, как классы, интерфейсы, наследование и полиморфизм.
В отличие от этого, в функциональном программировании применяется подход к вычислительным проблемам как к определению чисто функциональных преобразований коллекции данных. В функциональном программировании приходится отказываться от применения состояний и изменяющихся данных, а вместо этого сосредоточиваться на применении функции.
К счастью, C# и Visual Basic не требуют резкого перехода на функциональное программирование, поскольку поддерживают как императивный, так и функциональный подход. Разработчик может сам выбирать нужный подход в зависимости от конкретного сценария. В действительности в программах часто сочетаются оба стиля.
См. также
Основные понятия
Введение в чисто функциональные преобразования
Оптимизация кода для получения чистых функций