Так уж завелось на хабре, что на каждую холиваную статью «Pro» всегда найдётся статья «Contra».
Я тоже решил не оставлять в одиночестве Что не так с ООП и ФП
Прямо противоречить написанному смысла не имеет, там ведь описан «вкус», а, как известно, на вкус и цвет… каждый любит свой ЯП
Нет никакой проблемы с ООП и ФП. Чистота функций — это всего лишь инструмент, равно как и «всё является объектом».
Критика права лишь в одном — в борьбе за миллиметры хорошо видны яркие прорехи, а в любых вырожденных методах недостатки ярко проявляются.
Другое дело, что любые невырожденные методы так же имеют недостатки, только их больше, зато они не так легко заметны.
Любители С++ гнобят полное ООП, Javа гнобит Си++ за неполное ООП, Haskell гнобит другие ФП за грязные функции, остальные ФП гнобят Haskell за излишне чистые функции.
Всё имеет свою оборотную сторону медали.
Тогда почему досталось всё объектам и функциям, а не массивам и указателям?!
Эта статью можно назвать обобщением моей статьи
Развитие пользовательских типов данных в программировании
Чтобы понять, почему объекты и функции так провинились, давайте взглянем на языки сверху.
Пример 1
У нас есть и PHP и сайт-визитка. Почти наверняка, там почти отсутствует не только фреймворки, но и вообще внятная структура.
Если сайт этот будет медленно развиваться, у нас появятся функции, массивы, затем появятся объекты, вплоть до сильно-объектных фреймворков.
Как мы видим, растущая сложность сайта заставляет вводить сложность в программы. Самое парадоксальное, что сложность вводится для уменьшения сложности. Грамотно написанный сайт с использованием объектов проиграет, если всё переписать под процедурный подход.
Пример 2
Ассемблер. На нём можно написать даже операционную систему, как это делают, например, ребята из КолибриОС, но давайте будем откровенны, используют его там, где без него никак не обойтись.
Для чего-то простого в основном используют С, значительно реже Паскаль, Бейсик. И на С можно ОС написать (например, тот же Линукс), но сейчас он уже значительно реже используется для крупных проектов. И это при том, что С — лингва-франка многих языков программирования.
Растущая сложность алгоритмов уже не даёт интенсивно использовать возможности языка, приходится использовать экстенсивно!
Сейчас для сложных проектов используется Java, С++, C#,… — высоко-объектные языки.
Функциональное программирование можно рассматривать как альтернативный подход к решению сложности — Лисп и лисп-подобные языки сравнимы по мощности с С, OCaml сравним с С++ и даже выше (модули как функции имеют примерно ту же мощность, что и объекты), Haskell — выше Java (об этом ниже).
Суть заключается в том, что каждые методы/функции/объекты/… решают лишь свои диапазоны сложности.
И рассматривать 2+2
как объект(2).метод(+)(объект(2))
— говорит о том, что объект достаточно сложный объект, и на нём лёгкие вещи просто не программируются. Такие языки, как Rubi помогают синтаксическим сахаром понизить этот порог сложности.
Объекты
Утверждается в той статье ни много ни мало, что «ООП, так и ФП неэффективны, если доходить в их использовании до крайности».
Но думаю, не в этом их главная «вина».
Интенсивные решения с помощью объектов исчерпаны (для крупных проектов), и именно в этом заключается главная претензия к объектам — экстенсивные решения не дают той красоты, простоты и эффективности. И начинаются придирки. Например, такие: «функции являются фундаментальным понятием, в то время как объекты лишь содержат их».
Предлагаю взглянуть на эту придирку с другой точки зрения — рассматривать функцию как объект даёт нам инструмент масштабирования сложности.
Конечно же, под масштабированием понимается фрактальное масштабирование — если у нас есть проблема — решаем малые проблемы, а на масштаб выше решаем этими же методами более крупные проблемы, ещё на масштаб выше — ещё более крупные проблемы.
Объекты — это инструмент масштабирования наших задач. В упоминаемой моей статье я называл объекты пользовательскими данными, которые дают сохранить инструментарий по работе с ним в нём самом.
Именно это и дало объектам завоевать столь большую популярность — ими легко масштабировать вверх.
Пример 3
Планета Земля. Пусть мы программируем снизу вверх. У нас есть здания, сооружения и люди. На масштаб вверх будут посёлки, города и людские потоки. Ещё уровнем вверх надо смотреть на районы, области, мегаполисы и на миграцию населения. Ещё выше будут страны и народы. Ещё выше будут континенты и внешняя политика. Ещё выше будет Земля и человечество.
Однако, остановимся на недостатке фрактального масштабирования. Как известно, система — это совокупность элементов, при этом она обладает свойствами, которыми не обладает сумма элементов. Именно это маленькая, но самая существенная надбавка постепенно растворяется при фрактальном масштабировании — за каждый подъём уровня вверх приходится бороться, ибо надо нарушить фрактальность. В частности, поэтому предлагается не плодить слишком большую иерархию объектов.
Классы типов
Есть ли что-то, что более легко масштабируется, нежели объекты? Как я указал в другой статье — есть.
Это тип-классы (они же классы типов) в Хаскеле, подобный механизм, который ввела Scala (хотя там механизм достаточно сложный), и объектный аналог — роли в Perl.
Как видим, это далеко не самые популярные языки.
Если посмотреть, видно, что ныне тип-классы обогнали по мощности объекты и идут по интенсивному пути. Они ещё не упёрлись в потолок.
Вывод
Сложность программ нарастает. С ООП и ФП всё в порядке. Не в порядке лишь с быстрым масштабированием сложности, поскольку сложность растёт быстрее, нежели позволяют интенсивные возможности.
Автор: Vitter