Если кратко, то как ООП так и ФП неэффективны, если доходить в их использовании до крайности. Крайностью в ООП считается идея о том что “все что угодно является объектом” (чистое ОП). Крайностью для ФП можно рассматривать чистые функциональные языки программирования.
Что не так с ООП
Наиболее ошибочным для ООП является само понятие “объекта” и попытка определить что-угодно через него. В конце концов, вы доходите до концепции “все что угодно — это объект”. Но это не так, потому что:
Существуют вещи, которые не являются объектами. Функции не являются объектами.
Вы можете возразить, что в Python или Scala функции являются объектами. В Python любой объект с методом __call__
можно считать функцией. Точно также в Scala функции — это просто объекты с методом apply
. Тем не менее, тщательно поразмышляв над этим, можно заметить несоответствие теории с практикой. Дело в том, что функции являются фундаментальным понятием, в то время как объекты лишь содержат их. Мы пытаемся определить функции как объекты, которые содержат методы __call__
или apply
, но сами по себе эти методы уже являются “функциональными объектами”. Python и Scala просто похитили все функции, заключили их в тюрьму “объектов”, пометили как __call__
или apply
, а в конце концов назвали это “методами”. Конечно, если обернуть все функции в объект, появляется возможность обращаться с различными объектами как с функциями, но это еще не значит, что можно утверждать что “функции также являются объектами”.
Большинсвто ОО-языков также лишены нормальной реализации функций первого порядка. Кульминацией можно считать Java, которая вообще не позволяет передавать функции как данные. Да, вы всегда можете обернуть функции в объекты и назвать их “методами”, но, как я уже говорил, это всего лишь похищение. Отсутствие функции первого порядка является основной причиной тому, что существует такой множество "шаблонов проектирования" в Java. Но как только у вас есть функции первого порядка, в большинстве таких шаблонов просто нет никакой необходимости.
Что не так с ФП
Подобно ООП, концепция функционального программирования начинает больше вредить, когда вы доходите до крайности, а именно до чистых функциональных языков программирования. Для лучшего понимания было бы не лишним понимать, что называют чистым функциональным языком. Как вариант, вы можете прочесть «What is a Purely Functional Language» авторства Amr Sabry (он был моим консультантом при получении PhD). Если говорить в общем, чисто функциональные языки являются неправильным, потому что
Существуют вещи, которые не являются чистыми по своей сути. Побочные эффекты очень реальны.
Будучи чистыми, ФП-языки игнорируют возможности и ограничения, которые предоставляет физическая платформа (кремниевые чипы, квантовые чипы, не важно). Вместо этого ФП-языки пытаются заново реализовать окружающий мир, передавая на вход некоторых функций “состояние мира” и получая новое его состояние на выходе. Но существует разница между физическими процессами и их симуляцией. “Побочные эффекты” — это реальные процессы. Они действительно существуют в природе и являются необходимыми для того, чтобы эффективно производить вычисления. Попытка же имитировать побочные эффекты на основе чистых функций обречена быть не эффективной, сложной и скорее всего уродливой. Замечали ли вы, как легко реализовать на С кольцевую структуру данных или генератор случайных чисел? То же самое нельзя сказать о Haskell.
Кроме того, программирование на чистых функциональных языках требует огромных умственных усилий. Если вы посмотрите глубже на них, то поймете, что монады делают программы переусложненными и трудными для написания, а монадные трансформации являются просто уродливыми хаками. Все это очень похоже на “шаблоны проектирования” в Java. Вы заметили, как много тривиальных задач для других языков программирования становиться исследовательской проблемой при попытке реализовать их на Haskell? Постоянно выходят статьи с названием в стиле “Монадный подход к решению такой-то-уже-решенной-проблемы”. Иронично, но Amr Sabry (мой консультант) является со-автором одной из таких статей. Он пытался реализовать семейство языков miniKanren Дэна Фридмена, но так и не смог понять, каким образом сконструировать монады. Он попросил помощи у Олега Киселева, человека, который возможно лучше всех разбирается в системе типов Haskell. И, если вы не знаете, Amr Sabry, вероятно, самый осведомленный в мире человек по теме чистых функциональных языков программирования. Они стали соавторами целой статьи после того, как с помощью Олега, им все таки удалось реализовать желаемое. Ирония в том, что у Дена Фридмана не возникло вообще никаких проблем с реализацией этого куска кода на Scheme.
Некоторые люди утверждают, что значение монад в том, что они “ограждают” разработчиков от побочных эффектов. Но какой был бы толк от этого ограждения, если бы монады не делали ваш код более понятным или безопасным? А правда в том, что они не делают. Программы, написанные с применением монад так же сложно анализировать, как если бы они были напичканы побочными эффектами. Нет ничего такого, что можно сделать проще с помощью монад, и что не может быть сделано путем статического анализа. Любой исследователь статического анализа знает об этом. По существу, статические анализаторы кода основаны целиком на монадах, и тем самым они отбирают у программистов бремя по написанию монадического кода, вместо того, чтобы перекладывать его на них. Конечно, злоупотребление побочными эффектами делает программный код сложным для анализа, но с другой стороны никто не мешает вам писать чистые функции даже на С:
int f(int x) { int y = 0; int z = 0; y = 2 * x; z = y + 1; return z / 3; }
Вы можете сделать тоже самое и на ассемблере. Чистые функции не являются чем-то таким, что относиться исключительно к функциональному программированию. Вы можете создавать чистые функции на любом языке, но главное, вы должны иметь возможность также использовать побочные эффекты.
Оглядываясь назад в историю, идеализм математиков стал движущей силой чистых функциональных языков программирования. Математические функции просты и красивы, но к сожалению они работают хорошо только тогда, когда вы пытаетесь моделировать процессы чистые по своей сути. В противном случае они становиться уродливыми. Не стоит бояться базвордов вроде “Теория категорий”. Я знаю значительное количество различных теорий с таким названием. Даже исследователи теорий категорий порой называют их “абстрактной чепухой”, потому что по сути они занимаются лишь тем, что находят очередной нелепый способ сказать о том, что вы уже и так знаете! Если вы прочтете статью Готлоба Фреге “Function and concept”, то будете удивлены тому, как большинство математиков использовали функции неправильно, и это было всего лишь чуть более столетия назад. На самом деле, математики совершили много плохих вещей со своим языком, особенно в том, что касаться вычислений. Так что не существует никаких оснований в том, что проектировщики языков программирования должны слепо учиться этому у математиков.
Не нужно влюбляться в ваши модели
Что-угодно начинает приносить вред, когда вы начинаете пользоваться этим слишком часто. Доходя до крайности, как ООП так и ФП пытаются втиснуть мир в свою собственную своеобразную модель, но проблема в том, что мир существует независимо от того, что мы о нем думаем. Совершенно неприемлемо пытаться думать обо всем как о гвоздях только потому, что у вас в руках молоток. И только наблюдая за реальностью мы можем избавиться от тех религиозных заблуждений, которые в действительности ограничивают нас.
Не подгоняйте весь мир под ваши модели. Приспосабливайте вашы модели для окружающего мира.
ссылка на оригинал статьи http://habrahabr.ru/post/201874/
Добавить комментарий