💔

2.4. Почему ФП и ПП – не выход

К этому моменту мы с вами обнаружили что:
 
  1. Существует 2-х типа ООП: ООП синтаксис и ООП архитектура
  1. Скорее всего, вы никогда не программировали на «каноничном ООП», а использовали его микс с процедурным
  1. Основная проблема ООП – излишняя атомарность, убивающая гибкость приложения
 
Теперь давайте обсудим почему Функциональное программирование (ФП) и Процедурное Программирование не являются хорошими альтернативами, когда речь заходит о мультипарадигмальных языках.
 
Щас и поговорим, почему так получилось:

Функциональное программирование (ФП)

Одно из главных преимуществ функционального программирования, которое стало основой всех функциональных языков и конструкций – распараллеливание вычислений, доступное благодаря иммутабельности.
 
Сейчас объясню, что это значит.
 
Вот скажите мне, в какой последовательности, на неважно каком языке, запуститься эти функции:
 
const user = { name: "David" weight: 87 age: 27 } changeUserAge(user, 28) changeUserWeight(user, 92)
 
Если вы пришли не из функционального мира, то вы скажите, что сначала отработает changeUserAge, а потом changeUserWeight.
 
Но в функциональном мире, эти две функции запуститься одновременно.
 
Перед тем, как я дам ответ почему так устроено в обоих ситуациях, подумайте сами.
 
3… 2… 1…
 
Суть тут в том, как устроены мутации в вашем языке.
 
Если ваш язык разрешает вам мутировать любые данные (например, const user), тогда ему придется исполнять код последовательно, потому что он не может знать ждёт ли следующая функция (changeUserWeight) результатов мутаций предыдущей (changeUserAge).
 
А вот если ваш язык работает с имутабельными структурами и вы вызываете 2 функции, куда передаёте иммутабельную структуру, он может запустить обе функции в параллель, потому что он точно знает, что исходное значение не измениться.
 
А вот чтобы запустить их последовательно, используются специальные приемы континуации.
 
Эта особенность языка еще называется “stateless”, то есть «отсутствие состояния в языке программирования».
 
И именно из-за этой особенности, чтобы поддерживать «отсутствие состояния» появляются такие конструкции как Монады, Фукторы, Семигруппы, Пайпы и вся остальная магия ФП-шных языков.
 
Только встаёт вопрос: а нахрена нам все это использовать, если 99% мультипарадигмальных языков, statefull, мутабельные и без автоматического распаралелливания?
 
Так вот ответ: нам все это не нужно.
 
Мы не получим никаких преимуществ, доступных в ФП-шных языках и только получим кучу ненативных и сложных в понимании конструкций.
 
Ей ты богу, я лучше буду работать с чистейшим ООП на мультипарадгимальным языком, чем на ФП в том же языке.
 
Поэтому полноценный ФП для нас не вариант, НО мы сможем достать из ФП некоторые приемы и механизмы, которые будут нам супер полезны.

P.S.

Еще хочу уточнить то, что работа с иммутабельностью – очень непростая задача, которая может сильно усложнить кодовую базу и повлиять на скорость работы мультипарадигмальных языков, поэтому ФП нам не подходит, поскольку работа с мутабельными структурами в нем устроена совершенно не похоже на то, что мы делаем в мультипарадигмальных языках.

Процедурное программирование (ПП)

Процедурное программирование гораздо более подходящая альтернатива ООП и ФП, потому что она решает проблемы ООП (о чем ниже), но при этом не добавляет ненужной в мультипарадигмальных языках сложности ФП.
 
Проблема ПП в том, что оно с 90-х годов не эволюционировало.
 
В ПП нормально иметь и мутировать глобальное состояние (что является крайне опасным подходом), в нем нет столпов, нет приёмов наподобие композиции, каррирования и частичной аппликации (которые бывают очень полезны), нет понятия «функция высшего порядка» (что убирает много приёмов пробросать функций друг в друга) и так далее.
 
Все это также порождает проблему того, что вы не сможете погуглить как грамотно решать проблемы с точки зрения архитектуры на ПП, потому что этих правил архитектуры вообще нет.

А что хорошего в ФП и ПП

Во-первых, и ФП и ПП решают главную проблему ООП, о которой я писал в прошлой главе: излишняя атомарность.
 
Дело в том, что в обеих парадигмах, программа представляет собой набор функций, которые могут использовать любые интересующие их данные.
 
То есть, мы просто описываем данные:
 
А далее, на каждую новую фичу, можем создать функцию, которая принимает любые данные на вход и оперирует над ними:
 
Тем самым, мы не создаём никаких дополнительных слоев изоляции и на максимум используем «натуральную инкапсуляцию».
 
Этот подход называется «Разделение Данных и Поведения» (Data and Behavior Separation), в противовес ООП-ной Инкапсуляции.
 
Во-вторых, следствием этого подхода является отсутствие проблем с Cross Cutting Concern (потому что любая функция может использовать любые даннные), а также ненадобностью всяких паттернов типа SOLID (да, да, они просто не нужны).
 
Есть слайд, который отлично отображает данное следствие:
 
notion image
 
В-третьих, вместо Наследования и Классового полиморфизма из ООП, мы с вами можем активно пользоваться Композицией и Интерфейсными полиморфизмом (что даже в ООП считается best-practice)

И что нам тогда делать?

Именно из-за того, что я хотел использовать эти преимущества ПП и ФП, я создал Функциоанльно Ориентированное Программирование (ФОП).
 
ФОП основан на Процедурном программирование, но добавляет в него все фишки, которые мы получили благодаря развитию Функционального программирования, без излишнего усложнения.

Что дальше

Подытожим все вышесказанное в главе
🎉
2.5. Поэтому и появился (λ) ФОП
 


 
💡
Подписывайтесь на телеграм канал 🦾 IT-Качалка Давида Шекунца 💪, где будут выходить анонсы новых глав и обновления существующих. Спасибо за внимание и мощной вам прокачки 💪