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

Як відомо, програмісти — люди творчі, але разом з тим ревно дотримуються певних ідей, наприклад, вибору мови програмування. PHP вважається мовою «для ледачих», а JavaScript — «важкопрогнозованою» магією. І серед величезного розмаїття мов функціональні мови все швидше обростають шанувальниками і все впевненіше прокладають собі шлях в більшість компаній по всьому світу. Згідно аналітиці RedMonk від червня 2017 і збірної оцінки популярності мов на GitHub і Slack Overflow, функціональні мови (Elm, Elixir) повільно, але впевнено набирають зростання. Величезний зростання популярності JavaScript також веде до підвищеного інтересу до ФП. До того ж, розробники з досвідом у функціональному програмуванні згодом починали працювати над SPA фреймворками, і, як результат, у нас є Redux, React, MobX та інші бібліотеки, якими користуються мільйони людей.

Так що ж таке функціональне програмування, звідки такий бум і чому варто задуматися про його вивченні? Давайте розбиратися.

Трохи азов

Перш ніж йти в нетрі, варто почати зі старту.

Світ JavaScript кипить. Кілька років тому лише деякі розробники мали уявлення про функціональному програмуванні, а ось за останні три роки практично кожна кодова база великих додатків активно використовує ідеї, взяті зі світу функціонального програмування. І на те є об'єктивні причини: функціональне програмування дозволяє писати більш стислий і передбачуваний код, його легше тестувати (хоча вивчення з нуля дається нелегко).

Основні відмітні ознаки розробки ПЗ за допомогою ФП:

Функціональне програмування за своєю суттю ґрунтується на фундаментальних, визначальних принципах, перерахованих вище. І щоб почати їх осягати, спершу варто перейти в «академічний» режим і як слід вивчити визначення термінів, які будуть невідступно переслідувати вас в ФП: чисті функції, композиція функцій, уникнення розділяється стану і т. п. Це більше схоже на повернення в школу на урок математики — зате після цього ви зовсім по-іншому дивитиметеся і функціональний, і на програмування в цілому.

Давайте трохи заглибимося в терміни ФП і мінімально поверхнево розберемося, що вони означають.

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

Композиція функцій означає процес комбінування двох і більше функцій з метою створення нової функції або проведення обчислень.

Тепер зробимо паузу, выдохнем і повернемося до більш зрозумілих речей, а саме, до подільних станів . Основна проблема поділюваних станів — щоб розуміти ефекти функції, потрібно знати всю історію кожної поділюваної змінною, яку використовує функція. Тому функціональне програмування уникає поділюваних станів, замість цього покладаючись на незмінні структури даних і чисті обчислення з метою отримання нових даних з існуючих. Ще один нюанс, який виникає при роботі з розділяються станами — зміна порядку виклику функцій може спричинити за собою лавину помилок. Відповідно, уникаючи поділюваних станів, ви уникаєте цієї проблеми.

В основі всього функціонального програмування лежить незмінність (immutability). І тут важливо не плутати const з незмінністю. const створює зв'язування імені змінної, яке не може бути переприсвоено після створення, але воно не створює незмінні об'єкти. Ви не зможете змінити об'єкт, до якого відноситься зв'язування, але ви все ще зможете змінювати властивості цього об'єкта, відповідно, зв'язування, створені const, не є незмінними. Незмінні об'єкти взагалі не можуть бути змінені. Це досягається глибоким заморожуванням змінних.

І, якщо ви ще не зовсім втомилися, на секунду розглянемо побічні ефекти . Побічні ефекти означають, що крім повернення значення функція також взаємодіє із зовнішнім змінним станом. Чому ФП їх уникає? Тому що таким чином ефекти програми набагато легше розуміти і тестувати. Haskell, приміром, для ізоляції побічних ефектів від чистих функцій, використовує монади.

Отже, ваша голова, швидше за все, почала боліти, але обов'язково знайдеться хтось, хто запитає: так все-таки, чому декларативний, а не імперативний підхід? У чому сіль?

Сіль в тому, що імперативний підхід працює за принципом керування потоком і відповідає на питання «як робити». Декларативний підхід описує потік даних і відповідає на питання «що робити». До того ж, імперативний код найчастіше використовує інструкції (операторів), а декларативний більше покладається на вираження.

Отже, ми начебто розібралися з тим, що таке функціональне програмування і що потрібно про нього знати. І, перш ніж ми перейдемо до обговорення його переваг, пропоную спершу пройтися по недоліків — точніше, вникнути в суть стереотипу «функціональне програмування неприродно».

Щоб написати код, станьте кодом

Судячи з того, що я писала вище, серед читачів вже повинні були зародитися адепти функціонального програмування. Тим не менш, незважаючи на величезну кількість хвалебних статей, знаходиться не меншу кількість статей під назвами «Функціональне програмування дивне і не має майбутнього» (наприклад). Чи означає це, що я помиляюся? Немає. Чи є причини вважати ФП дивним? Зрозуміло.

Дозвольте наведу цитату, взяту з просторів Інтернету, яка повністю відображає ставлення багатьох розробників до ФП:

«Написання функціонального коду — немов написання задом наперед і найчастіше схоже на розгадування головоломки, а не на пояснення процесу комп'ютера».

Насправді, це досить суб'єктивне ставлення до ФП тих, хто не хоче приділити достатню кількість часу, щоб розібратися в нюансах функціонального програмування і просто спробувати. Але, як я і обіцяла, розберемо недоліки ФП, щоб потім перейти до переваг.

Недоліки

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

Також ФП не підходить для алгоритмів на графах (за рахунок повільної роботи) і в цілому для тих рішень, які десятиліттями ґрунтувалися на імперативний програмуванні.

Гаразд, останній пункт більше звучить як причіпка — ми не можемо звинувачувати ФП в тому, для чого воно не було призначено. Тому пропоную звернутися до приємного, а саме — до переваг ФП та його використання в реальних проектах реальними міжнародними компаніями.

Переваги

Один з найбільш явних плюсів функціонального програмування — це високорівневі абстракції, які приховують велику кількість подробиць таких рутинних операцій, як, наприклад, итерирование. За рахунок цього код виходить коротше, і, як наслідок, гарантує меншу кількість помилок, які можуть бути допущені.

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

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

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

Зрозуміло, не можна заперечувати переваги ООП, але варто пам'ятати і про те, що функціональні мови по своїй зручності стоять нарівні з багатьма іншими і гідні вашої уваги.

Гребінь хвилі IT-трендів і застосування ФП

У світі IT нічого не відбувається просто так. Одне чіпляється за інше, і ось вже всі самі «гарячі» тренди пов'язані між собою.

Якщо згадувати найбільш гучні тренди 2016-2017 року, це, зрозуміло, будуть AI, IoT, Big Data і Blockchain. Вони у всіх на слуху, всім відомий їхній потенціал і ключові особливості. І саме деякі з цих трендів послужили каталізатором зростання популярності функціонального програмування серед розробників.

В даний час дуже гостро стоїть проблема паралельної обробки та роботи з великими потоками даних, іншими словами, робота з Big Data. І, распараллелив обробку цих даних, можна отримати бажаний результат за частку секунди, що дуже критично в реальному світі. Плюс не забувайте про децентралізованих (розподілених) обчисленнях — блокчейнах та інших, які, по суті своїй, є досить складним механізмом. І для таких обчислень функціональний код підходить більше всього за рахунок усіх принципів функціонального програмування (таких, як чисті функції, наприклад). Використання всіх базових прийомів ФП полегшує паралельне виконання коду і його підтримку.

До того ж, якщо раніше функціональне програмування використовувалося тільки для вирішення специфічних завдань, то тепер воно застосовується навіть на класичних проектах. З чого можна сміливо робити висновок: великим IT — компаніям не варто сумніватися з приводу використання функціонального програмування, а як приклад можна привести один з проектів Intetics, на якому займаються розробкою просунутих Front-end додатків з інтерактивним UI.

Суть проекту

Ще до того, як команда Intetics приєдналася до проекту, замовник розробив власний функціональний мову програмування. Про причини ми поговоримо трохи пізніше, а поки що відповімо на питання: чому саме функціональне програмування?

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

Замовник був не тільки інноватором (на той момент це було перше подібне рішення на ринку), але і досить проникливим людиною. Він розгледів всі переваги функціонального програмування раніше своїх конкурентів, і це дало йому змогу забезпечувати високу якість свого продукту та підтримувати його відповідно до вимог. Тобто ФП забезпечувало лаконічність коду, плюс, підходило клієнту за стилем. Справедливості заради варто сказати: ООП теж підходить під вирішення завдань проекту, і замовник пробував кілька мов, але вибір все ж зупинив на функціональному програмуванні.

Говорячи про причини розробки власної мови, не забувайте, що ми говоримо про проект десятирічної давності. У той час не було достатньо розвинених кросплатформених фреймворків, придатних для даних завдань, і тому замовник просто взяв і створив власний — flow для швидкого створення UI під різні платформи. І це дуже полегшує роботу, дозволяючи швидко впроваджувати будь-які зміни і вирішувати будь-які завдання, пов'язані з проектом. До того ж, кросплатформених функціональних мов дуже мало, так що проект дійсно виділяється серед своїх аналогів.

Висновок — не бійтеся пробувати

Як ви вже напевно зрозуміли, функціонального програмування побоюватися не варто. Трохи старанності і допитливості, і ось ви вже освоїли ФП. Ось декілька порад тим, хто зважився спробувати себе в новому жанрі і вивчити щось кардинально нове:

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

Опубліковано: 01/02/18 @ 11:43
Розділ Різне

Рекомендуємо:

Огляд IT-ринку праці: Полтава
DOU Проектор: Liki24 — сервіс доставки ліків за низькими цінами
Зарплати розробників України — грудень 2017
PHP дайджест #11: найпопулярніші помилки в коді на PHP, реліз Composer 1.6.0, Developer Survey 2018
iOS дайджест #23: потрібно більше архітектур, Apple купила Buddybuild, майбутнє face-controlled додатків