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

В этом разделе сравнивается и противопоставляется функциональное программирование с традиционным императивным (процедурным) программированием.

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

Принципы функционального программирования формулировались специально для поддержки чисто функционального подхода к решению проблем. Функциональное программирование является одной из форм декларативного программирования. В отличие от этого, большинство традиционных языков, в том числе такие языки объектно-ориентированного программирования (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 не требуют резкого перехода на функциональное программирование, поскольку поддерживают как императивный, так и функциональный подход. Разработчик может сам выбирать нужный подход в зависимости от конкретного сценария. В действительности в программах часто сочетаются оба стиля.

См. также

Основные понятия

Введение в чисто функциональные преобразования

Оптимизация кода для получения чистых функций

Другие ресурсы

Преобразования XSLT