Pull to refresh

Что так с ООП и ФП, и что не так с программированием

Designing and refactoringООPFunctional Programming
Так уж завелось на хабре, что на каждую холиварную статью «Pro» всегда найдётся статья «Contra».
Я тоже решил не оставлять в одиночестве пост «Что не так с ООП и ФП».



Прямо противоречить написанному смысла не имеет, там ведь описан «вкус», а, как известно, на вкус и цвет… каждый любит свой ЯП.
Нет никакой проблемы с ООП и ФП. Чистота функций — это всего лишь инструмент, равно как и «всё является объектом».
Критика права лишь в одном — в борьбе за миллиметры хорошо видны яркие прорехи, а в любых вырожденных методах недостатки ярко проявляются.
Другое дело, что любые невырожденные методы так же имеют недостатки, только их больше, зато они не так легко заметны.
Любители С++ гнобят полное ООП, Javа гнобит Си++ за неполное ООП, Haskell гнобит другие ФП за грязные функции, остальные ФП гнобят Haskell за излишне чистые функции.
Всё имеет свою оборотную сторону медали.
Тогда почему досталось всё объектам и функциям, а не массивам и указателям?!

Эту статью можно назвать обобщением моей статьи «Развитие пользовательских типов данных в программировании».
Чтобы понять, почему объекты и функции так провинились, давайте взглянем на языки сверху.

Пример 1

У нас есть и PHP и сайт-визитка. Почти наверняка, там почти отсутствует не только фреймворки, но и вообще внятная структура.
Если сайт этот будет медленно развиваться, у нас появятся функции, массивы, затем появятся объекты, вплоть до сильно-объектных фреймворков.
Как мы видим, растущая сложность сайта заставляет вводить сложность в программы. Самое парадоксальное, что сложность вводится для уменьшения сложности (при этом переходя на более высокий уровень абстракции). Грамотно написанный сайт с использованием объектов проиграет, если всё переписать под процедурный подход.

Пример 2

Ассемблер. На нём можно написать даже операционную систему, как это делают, например, ребята из КолибриОС, но давайте будем откровенны, используют его там, где без него никак не обойтись.
Для чего-то простого в основном используют С, значительно реже Паскаль, Бейсик. И на С можно ОС написать (например, тот же Линукс), но сейчас он уже значительно реже используется для крупных проектов. И это при том, что С — лингва-франка многих языков программирования.
Растущая сложность алгоритмов уже не даёт интенсивно использовать возможности языка, приходится использовать экстенсивно!

Сейчас для сложных проектов используется Java, С++, C#,… — высоко-объектные языки.
Функциональное программирование можно рассматривать как альтернативный подход к решению сложности — Лисп и лисп-подобные языки сравнимы по мощности с С, OCaml сравним с С++ и даже выше (модули как функции имеют примерно ту же мощность, что и объекты), Haskell — выше Java (об этом ниже).

Суть заключается в том, что каждые методы/функции/объекты/… решают лишь свои диапазоны сложности.
И рассматривать 2+2 как объект(2).метод(+)(объект(2)) — говорит о том, что объект достаточно сложная сущность, и на нём лёгкие вещи просто не программируются. Такие языки, как Ruby помогают синтаксическим сахаром понизить этот порог сложности.

Объекты


Утверждается в той статье ни много ни мало, что «ООП, так и ФП неэффективны, если доходить в их использовании до крайности».

Но думаю, не в этом их главная «вина».
Интенсивные решения с помощью объектов исчерпаны (для крупных проектов), и именно в этом заключается главная претензия к объектам — экстенсивные решения не дают той красоты, простоты и эффективности. И начинаются придирки. Например, такие: «функции являются фундаментальным понятием, в то время как объекты лишь содержат их».

Предлагаю взглянуть на эту придирку с другой точки зрения: если рассматривать функцию как объект, то можно заметить, что она также является инструментом масштабирования сложности.
Конечно же, под масштабированием понимается фрактальное масштабирование — если у нас есть проблема — решаем малые проблемы, а на масштаб выше решаем этими же методами более крупные проблемы, ещё на масштаб выше — ещё более крупные проблемы всё теми же методами.
Объекты — это инструмент масштабирования наших задач. В упоминаемой моей статье я называл объекты пользовательскими данными, которые дают сохранить инструментарий по работе с ним в нём самом.
Именно это и дало объектам завоевать столь большую популярность — ими легко масштабировать вверх.

Пример 3

Планета Земля. Пусть мы программируем снизу вверх. У нас есть здания, сооружения и люди. На масштаб вверх будут посёлки, города и людские потоки. Ещё уровнем вверх надо смотреть на районы, области, мегаполисы и на миграцию населения. Ещё выше будут страны и народы. Ещё выше будут континенты и внешняя политика. Ещё выше будет Земля и человечество.

Однако, остановимся на недостатке фрактального масштабирования. Как известно, система — это совокупность элементов, при этом она обладает свойствами, которыми не обладает сумма элементов. Именно это маленькая, но самая существенная надбавка постепенно растворяется при фрактальном масштабировании — за каждый подъём уровня вверх приходится бороться, ибо надо нарушить фрактальность. В частности, поэтому предлагается не плодить слишком большую иерархию объектов.


Классы типов


Есть ли что-то, что более легко масштабируется, нежели объекты? Как я указал в другой статье — есть.
Это тип-классы (они же классы типов) в Хаскеле, подобный механизм, который ввела Scala (хотя там механизм достаточно сложный), и объектный аналог — роли в Perl.
Как видим, это далеко не самые популярные языки.
Если посмотреть, видно, что ныне тип-классы обогнали по мощности объекты и идут по интенсивному пути. Они ещё не упёрлись в потолок.

Вывод


Сложность программ нарастает. С ООП и ФП всё в порядке. Не порядок лишь с быстрым масштабированием сложности, поскольку сложность растёт быстрее, нежели позволяют интенсивные возможности.
Tags:фпоопхоливар
Hubs: Designing and refactoring ООP Functional Programming
Total votes 75: ↑47 and ↓28+19
Views25K

Popular right now