Сегодня мы коснемся темы функционального программирования, а именно различия между декларативным и императивным программированием.
Сначала давай быстро пробежимся по терминам, а потом сравним эти стили программирования и посмотрим, как они отражаются в Java и могут ли сосуществовать в данном языке.
Функциональное программирование — это парадигма, в которой процесс вычисления определяется вычислением значений функций в математическом их понимании, а не в понимании подпрограмм, как в процедурном программировании. То есть в этих двух парадигмах значение слова “функция” трактуется по-разному. Это нужно запомнить и не путать. В Java ты с этим не запутаешься: функции в значении подпрограмм — это “методы”, а функции как математические функции — это просто “функции” (также: лямбда-функции или method reference).
На практике в процедурном программировании функции зависят не только от входных переменных, но и от внешних факторов (например, других переменных вне функции или состояния системы). Таким образом при вызове одной и той же функции с одинаковыми аргументами в различном контексте могут получаться разные результаты. В функциональном же программировании при вызове функции с одинаковыми аргументами мы всегда получаем одинаковый результат, так как функции зависят только от входных данных.
Положительные стороны функционального программирования
- Повышение надежности кода
- Удобство организации модульного тестирования
- Возможности оптимизации кода при компиляции
- Возможности параллелизма
Отрицательные стороны функционального программирования
Недостатки функционального программирования вытекают из все тех же его особенностей:
Отсутствие присваиваний и замена их на порождение новых данных приводят к необходимости постоянного выделения и автоматического освобождения памяти. Поэтому в системе исполнения функциональной программы обязательным компонентом становится высокоэффективный сборщик мусора.
Нестрогая модель вычислений приводит к непредсказуемому порядку вызова функций, что создает проблемы при вводе-выводе, где порядок выполнения операций важен.
Краткая справка по функциональному программированию завершена, теперь перейдем непосредственно к стилям программирования.
Императивное программирование — это парадигма программирования, для которой характерны следующие черты:
В исходном коде программы записываются инструкции (команды).
Инструкции должны выполняться последовательно.
Данные, получаемые при выполнении предыдущих инструкций, могут читаться из памяти последующими инструкциями.
Данные, полученные при выполнении инструкции, могут записываться в память.
Основные черты императивных языков:
- Использование именованных переменных.
- Использование оператора присваивания.
- Использование составных выражений.
- Использование подпрограмм.
Императивная программа похожа на приказы, выражаемые повелительным наклонении в естественных языках, то есть представляют собой последовательность команд.
К императивным языкам программирования относятся C, C++.
Декларативное программирование — парадигма программирования, в которой задается спецификация решения задачи, то есть описывается конечный результат, а не способ его достижения. В качестве примеров декларативных языков можно привести язык разметки HTML. При написании тегов в этом языке мы не задумываемся о том, как элементы будут отрисовываться на странице, мы просто описываем, как эта страница должна выглядеть.
Другой язык декларативного программирования — SQL.
Чтобы сравнить два стиля программирования, рассмотрим пример из реальной жизни: как объяснить человек, как добраться до какого-то места?
Представим ситуацию: к нам подошел человек на улице и спросил: “Как пройти к музею N?”
При императивном подходе мы бы объясняли ему алгоритм того, как добраться туда пешком:
- сейчас развернуться
- идти 2 квартала по прямой
- повернуть направо
- …
При декларативном же подходе мы просто называем адрес, а дальше человек сам, своими силами (инструментами) добирается до нужного места.
Java же на данный момент является мультипарадигмальным языком программирования. Мультипарадигменность заключается в том, что язык поддерживает несколько парадигм.
Во время своего долгого развития язык расширял свою объектно-ориентированную модель для того, чтобы его пользователи получали различные инструменты и могли выбрать лучший для решения каждой конкретной задачи.
Поэтому на данный момент Java поддерживает как и императивный (например, написание кода вызовов методов), так и декларативный подход (например, аннотации, доступные в Runtime).
Подведем итог:
Существуют различные парадигмы программирования.
Есть декларативный и императивный подходы.
Выбирать стоит тот, который лучше будет справляться с решением поставленных задач.
Java — мультипарадигменный язык, поддерживающий оба подхода.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ