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