Сьогодні ми поговоримо на тему функціонального програмування, а саме — про відмінності між декларативним та імперативним програмуванням.

Спочатку давай розглянемо терміни, а потім порівняємо ци стилі програмування і подивимося, як їх відображено в Java і чи можуть вони співіснувати в цій мові.

Функціональне програмування — це парадигма, в якій процес обчислення визначається обчисленням значень функцій у їхньому математичному розумінні, а не у розумінні підпрограм, як у процедурному програмуванні. Тобто у цих двох парадигмах значення слова “функція” тлумачиться по-різному. Це потрібно запам'ятати і не плутати. Власне, у Java ти з цим і не заплутаєшся: функції в значенні підпрограм — це “методи”, а функції як математичні функції — це просто “функції” (також: лямбда-функції або method reference).

На практиці у процедурному програмуванні функції залежать не лише від вхідних змінних, а й від зовнішніх факторів (наприклад, інших змінних поза функцією або станом системи). Таким чином під час виклику однієї і тієї ж функції з однаковими аргументами в різному контексті можуть бути різні результати. У функціональному програмуванні під час виклику функції з однаковими аргументами ми завжди отримуємо однаковий результат, оскільки функції залежать лише від вхідних даних.

Позитивні сторони функціонального програмування

  • Підвищення надійності коду
  • Зручність організації модульного тестування
  • Можливості оптимізації коду при компіляції
  • Можливості паралелізму

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

Недоліки функціонального програмування так само випливають з його особливостей:

  • Через відсутність привласнень та їхню заміну на породження нових даних необхідно постійно виділяти та автоматичного звільняти пам'ять. Тому в системі виконання функціональної програми обов'язковим компонентом стає високоефективний збирач сміття.

  • Нестрога модель обчислень призводить до непередбачуваного порядку виклику функцій, що створює проблеми під час введення-виведення, де порядок виконання операцій важливий.

Коротку довідку про функціональне програмування завершено, тож перейдемо безпосередньо до стилів програмування.

Імперативне програмування — це парадигма програмування, якій притаманні такі риси:

  • У початковому коді програми записуються інструкції (команди).

  • Інструкції мають виконуватися послідовно.

  • Дані, що отримано під час виконання попередніх інструкцій, можуть читатися з пам'яті наступними інструкціями.

  • Дані, що отримано під час інструкції, можуть записуватися до пам'яті.

Головні риси імперативних мов:

  • Використання іменованих змінних.
  • Використання оператора присвоєння.
  • Використання складених виразів.
  • Використання підпрограм.

Імперативна програма схожа на накази, що виражаются у наказовому способі у природних мовах, тобто є послідовність команд.

До імперативних мов програмування належать C, C++.

Декларативне програмування — парадигма програмування, в якій встановлюється специфікація вирішення задачі, тобто описується кінцевий результат, а не спосіб його досягнення. Як приклад декларативних мов можна навести мову розмітки HTML. При написанні тегів у цій мові ми не замислюємося про те, як елементи будуть промальовуватись на сторінці: ми просто описуємо, як ця сторінка має виглядати.

Інша мова декларативного програмування — SQL.

Щоб порівняти два стилі програмування, розглянемо приклад із реального життя: як пояснити людині, як дістатися якогось місця?

Уявімо ситуацію: до нас підійшла людина на вулиці і запитала: "Як пройти до музею N?"

При імперативному підході ми би пояснювали йому алгоритм того, як дістатися туди пішки:

  • зараз розвернутися
  • йти 2 квартали по прямій
  • повернути направо

При декларативному підході ми просто називаємо адресу, а далі людина сама, своїми силами (інструментами) дістається до потрібного місця.

Java наразі є мультипарадигмовою мовою програмування. Мультипарадигменність полягає в тому, що мова підтримує кілька парадигм.

За час довгого розвитку мова розширювала свою об'єктно-орієнтовану модель, щоб її користувачі отримували різні інструменти та мали змогу обрати найкращий для вирішення конкретного завдання.

Тому нині Java підтримує і імперативний (наприклад, написання коду виклику методів), і декларативний підхід (наприклад, анотації, доступні в Runtime).

Підіб'ємо підсумки:

  • Існують різні парадигми програмування.

  • Є декларативний та імперативний підходи.

  • Обирати варто той, який зможе краще впоратися з вирішенням наявних задач.

  • Java — мультипарадигмова мова, яка підтримує обидва підходи.