понедельник, 18 октября 2010 г.

[prog] Цитата из Буча об истоках противостояния ООП и ФП

На досуге пытаюсь перечитывать книгу Гради Буча “Объектно-ориентированный анализ и проектирование”. Наткнулся на интересный фрагмент (раздел 1.3, курсивом выделена сноска и именно в ней все самое интересное):

Какая декомпозиция сложной системы правильнее - по алгоритмам или по объектам? В этом вопросе есть подвох, и правильный ответ на него: важны оба аспекта. Разделение по алгоритмам концентрирует внимание на порядке происходящих событий, а разделение по объектам придает особое значение агентам, которые являются либо объектами, либо субъектами действия. Однако мы не можем сконструировать сложную систему одновременно двумя способами, тем более, что эти способы по сути ортогональны [Лэнгдон предполагает, что эта ортогональность изучалась с древних времен. Он пишет: "К. X. Ваддингтон отметил, что такая дуальность взглядов прослеживается до древних греков. Пассивный взгляд предлагался Демокритом, который утверждал, что мир состоит из атомов. Эта позиция Демокрита ставила в центр всего материю. Классическим представителем другой стороны - активного взгляда - был Гераклит, который выделял понятие процесса"[Langdon, G. 1982. Computer Design. San Jose, CA: Computeach Press, p.6.]].

Она как! Истоки нужно искать еще в Древней Греции :)

17 комментариев:

Rustam комментирует...

Разделение по алгоритмам может и концентрирует внимание на порядке происходящих событий, однако функциональное программирование как раз (отсутствие побочных эффектов и ссылочная прозрачность) акцентирует внимание на том что порядок вычислений не важен, важнее декларативное описание, а в чистых ФЯ даже приходится идти на всякие ухищрения (CPS, монады) чтобы обеспечить нужный порядок вычислений.

eao197 комментирует...

Здесь, имхо, ты слишком акцентируешься на "порядке". Если же сделать водораздел на границе "процессов" (функций) и "атомов" (объектов), то все сходится.

Имхо, алгоритм есть математическое понятие. Поэтому не нужно ставить равенство между алгоритмом и побочными эффектами.

имя комментирует...

Буч говорил о том, что щас называется процедурным программированием (а не ФП); ФП имеет некоторый уклон в сторону возникшего во времена эйлера 3-го взгляда на природу -- смотри например "принцип наименьшего действия"

eao197 комментирует...

@имя:

на мой взгляд, между процедурным и функциональным подходом нет принципиальных отличий. На первом месте стоят действия по достижению конкретного результата (т.е. алгоритм). Различия только в количестве "разрешенных" побочных эффектов.

имя комментирует...

> Различия только в количестве "разрешенных" побочных эффектов.

Это только в том случае, если пытаться смешать функциональное и процедурное программирование (хотя это и перспективно и интересно); само же по себе ФП несет в себе совсем другую идеологию, принципиально несовместимую с *любыми* побочными эффектами (ПП) и изменениями состояния объекта (ООП) -- объект при своем изменении теряет identity.

Т.е. я в общем-то согласен с Рустамом.

eao197 комментирует...

>само же по себе ФП несет в себе совсем другую идеологию, принципиально несовместимую с *любыми* побочными эффектами

Из-за этого "чистого ФП" в реальном программировании нет. Есть математика и есть программирование, в котором приходится считаться с массой вещей. В том числе и с наличием ПП. Причем, по сути, производство ПП и есть цель любой программы.

>изменениями состояния объекта (ООП) -- объект при своем изменении теряет identity

Для меня разница между ООП и процедурным/функциональным программированием заключается не в том, связаны ли объекты с изменениями и теряют ли объекты identity при модификации.

Разница заключается в подходе к проектированию. В ООП мы выделяем автономные сущности, от деталей которых мы можем на конкретном этапе абстрагироваться почти что полностью. И как раз в ООП проблема в том -- какими сущностями ограничиться, каким данными и операциями их снабдить, как выстроить их иерархии. И наложить все это на операции, которые программа должна выполнять.

Тогда как в ФП и процедурном подходе мы проектируем в рамках действий-функций.

имя комментирует...

> Причем, по сути, производство ПП и есть цель любой программы.

Ну это ты так считаешь, поскольку пишешь такие программы (вероятно для телекома).

А теоретики заметили, что такие программы вообще бывают, не очень давно, и даже, похоже не успели придумать к ним методы верификации (ирония).

Справедливости ради -- полно команднострочных утилит, которые работают как чистые функции, если считать, что им передаются файлы (а не строки).

> И как раз в ООП проблема в том -- какими сущностями ограничиться, каким данными и операциями их снабдить

бывает полезен взгляд "какими инвариантами их снабдить" (вместо операций), кстати его выдвигал Страуструп; он похожее более общий

> Тогда как в ФП и процедурном подходе мы проектируем в рамках действий-функций.

То, что ФП все же больше на тему функций, а не объектов, это однозначно. Интересно было бы подумать над аналогом ФП, но для объектов.

eao197 комментирует...

>Справедливости ради -- полно команднострочных утилит, которые работают как чистые функции, если считать, что им передаются файлы (а не строки).

В пределе и они не чистые -- они оставляют следы на консоли или в перенаправленном канале ввода-вывода. :)

имя комментирует...

недиалоговая программа, которая пишет в поток (терминал), и при этом не читает то, что было в этом потоке в прошлом (и в будущем :-), вполне может считаться программой без побочных эффектов; результатом работы такой программы будет tuple из выхлопов в отдельные файлы (включая терминал)

eao197 комментирует...

>результатом работы такой программы будет tuple из выхлопов в отдельные файлы (включая терминал)

С учетом возможных ошибок ввода/вывода и блокировок программы при выводе (переполнение канала) -- не будет. :)

Rustam комментирует...

Абстрактная чистота не важна. Того что функциональные языки, даже нечистые (например тоже ML семейство) поощряют писать в функциональном стиле достаточно. Грязь и побочные эффекты изолируются основная масса кода при этом остается функциональной, уже это дает намного более надежный код. Ну и плюс конечно выразительность.

eao197 комментирует...

@Rustam: намного более надежный по сравнению с чем?

По-моему, даже Turbo Pascal с проверками на выход за пределы массивов и отсутствием адресной арифметики позволял делать намного более надежный код по сравнению с C++.

Rustam комментирует...

Намного более надежный код по сравнению с любым императивным языком. Кстати в C++ хоть const есть, но другие его недостатки его нейтрализуют.

eao197 комментирует...

>Намного более надежный код по сравнению с любым императивным языком.

А за счет чего по-твоему?

Rustam комментирует...

За счет неизменяемых структур данных. В такой структуре на порядки меньшее число возможных состояний и соответственно возможностей допустить ошибку. Да даже тот же элементарный const в C++ уже прилично усиливает надежность.
Здесь http://fprog.ru/2009/issue1/eugene-kirpichov-fighting-mutable-state/ про мутабельность и ее недостатки неплохо написано.

eao197 комментирует...

>Здесь http://fprog.ru/2009/issue1/eugene-kirpichov-fighting-mutable-state/ про мутабельность и ее недостатки неплохо написано.

Не понравилась мне эта статья. Во-первых, в начале статьи приведены примеры, которые показывают как все хреново с изменяемым состоянием. Но не показано затем, как все исправить с помощью неизменяемых состояний. В особенности интересно было бы про корзинку покупателя в магазине узнать.

Во-вторых, все эти проблемы более актуальны для языков с GC и с только ссылочными типами (вроде Java). Как ты правильно сказал, даже C++ const уже сильно меняет ситуацию.

Rustam комментирует...

Да примеры конечно не очень, но тема вполне раскрыта по моему.
А C++ как всегда с одной стороны низкоуровневый с другой есть возможности просто недоступные в управляемых языках.