☠️

2.3. Неисправимая проблема ООП

Предисловие

Сколько я не пытался написать эту главу, она все равно не настолько хороша, насколько это видео:
 
Video preview
 
Я невероятно настоятельно рекомендую посмотреть его, а потом продолжайте читать, потому что он невероятно подробно и понятно раскрывает проблемы, о которой я говорю.

В предыдущих главах

 
  1. Мы узнали о 3-х видах ООП
  1. Выяснили, что, скорее всего, вы никогда не программировали на «каноничном ООП», а использовали его микс с процедурным
 
В этой главе не буду затрагивать проблемы столпов ООП, об этом написано достаточно статей (ссылка на одну из самых лучших, которые я нашёл), я хочу затронуть гораздо более важную и корневую проблему:
 
Излишняя атомарность ООП
 
И под “атомарностью” я имею ввиду искуственную инкапсуляцию, которая лежит в основе ООП. А если есть “искусственная инкапсуляция”, то есть и “натуральная”.

Натуральная инкапсуляция

Натуральная инкапсуляция – это сокрытие, кода, которое происходит само собой, по факту устройства ОС, компьютера, физических законов и т.д.
 
Например, “Замыкание”, “Область видимости” или “Контекст” благодаря которым мы имеем или не имеем доступ к данным из другой области видимости является примером инкапсуляции:
 
const someFn = () => { const someVar = 1; // Эта переменная доступна только в рамкаъ данной функции } const someOtherFn = () => { console.log(someVar) // Собственно, благодаря "инкапсуляции" у нас не будет доступна эта переменная }
 
 
Или же, натуральная инкапсуляция существует на уровне любого приложения: вся кодовая база ваша приложения скрыта внутри него самого и наружу оно отдает только некоторое API.
 
notion image
 
 
Такая же натуральная инкапсуляция хорошим примером будет инкапсуляция на уровне библиотек, framework-ов и SDK, поскольку мы используем только данные нам создателями открытие методы работы с ними, при этом внутреннее устройство остается нетронутым.

ООП инкапсуляция

ООП же предлагает делить наше приложение, которое итак имеет натуральную инкапсуляцию, на еще более маленькие “атомы”, которые в ООП называются “объектами”.
 
notion image
 

Проблема ООП инкапсуляции

В рамках приложения, которое по идее должно иметь возможность оперировать над доступными ей данными и процессами, мы создаём дополнительные слои изоляции.
 
Именно эта излишняя изоляция и приводит к тому, что приложения на ООП теряют гибкость.
 
«Гибкость» – это возможность быстрого и удобного изменения логики приложения.
 
Когда вы делите свою кодовую базу на граф «объектов», вы лишаете себя этой самой гибкости, потому что теперь любое изменение, которое не попадает в данный граф (а такие 100% будут) потребует или создания костылей (публичных свойств и …Service объектов) или перестроения графа с созданием еще больше запутанных связей.
 
И ВЫ НИЧЕГО НЕ МОЖЕТЕ С ЭТИМ СДЕЛАТЬ.
 
Как только вы начали использовать ООП, и делить свою программу на умные “объекты” вы сразу попадаете в эту ловушку и единственным выходом из нее является только отказ от ООП.

Если ООП настолько плох, то почему его используют?

 
Тут есть 2 причины:
 
  1. На ООП можно создать качественную программу
  1. Маркетинг
 

Создание программы на ООП

А теперь ооочень интересная мысль и крючок, на который людей подсаживают пропагандируя ООП, DDD, Clean Architecture и подобные методологии:
 
Вы можете создать качественную программу, используя ООП, и это правда.
 
Потому что когда вы создаёте приложение у вас (1) нет никакой исходной кодовой базы, (2) вы с нуля изучите проблемы и задачи и спроектируете граф объектов, который прекраснейшим образом решит все поставленные проблемы.
 
Но практически никто после этого не говорит о том, с чем они сталкиваются, когда система уже создана и ее пора развивать.
 
А практически любая система сначала «создаётся», а потом «развивается».
 
И именно в момент появления новых требования вы осознаёте, что вся эта ваша архитектура, которая так хорошо решала проблемы в момент ее создания, не подходит под новые требования и придется не «добавлять новый функционал», а «переделывать старый, чтобы добавить новый».
 
Кто-то скажет: «Это потому что вы просто неправильно писали код» – а я скажу, что нет, как бы вы его «правильно» не писали, абсолютно всегда, если система развивается, первоначальные требования станут невалидны, а значит со временем любая архитектура становится «неправильной».
 
И ЕСТЬ ПОДХОД ПРИ КОТОРОМ ВАША ПРОГРАММА ОСТАНЕТСЯ ГИБКОЙ, и именно его посвящена данная книга. Я вам обещаю, что если вы дочитаете ее до конца и попробуете ФОП, вы поразитесь, тому насколько реально гибкой способна быть программа и поймёте почему все это время ООП забирало у вас эти возможности.
 

Маркетинг

Второй причиной популярности ООП, является маркетинг.
 
Нулевым пациентом ООП стала Java, из-за которой ООП кода стало настолько популярным:
 
  1. На момент появления Java у неё были только процедурные и функциональные языки программирования, где первые были слишком примитивны, а вторые слишком сложные, поэтому Java стала очень быстро набирать обороты в то время.
  1. Маркетинг Java настолько быстро набирал обороты, что многие языки решили откусить и себе кусок аудитории и начали создавать Java подобные языки.

А что произошло со временем?

 
Именно исторический контекст стал причиной популярности ООП кода. Но время идёт и мы видим, как люди постепенно начинают одумываться:
 
  1. Языки типа Java, Ruby и C# добавляют к себе lambda функции (а это конструкция из ФП, а не ООП)
  1. Golang, Rust, Kotlin, Zig и Nim имеют ООП-подобные конструкции, но являются мультипарадигмальными языками, с упопром на процедурное и даже функциональное программирование.
  1. Появляются упрощённые функциональные языки типа Elixir, Scala и F#
  1. Unity обращается в сторону функционального подхода ECS (DOTs) вместо прежнего ООП-оного подхода
 

Альтернативы ООП

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