Как сторонники функционального программирования ответят на это утверждение в Code Complete?


30

На странице 839 второго издания Стив Макконнелл обсуждает все способы, с помощью которых программисты могут «преодолевать сложности» в больших программах. Его советы завершаются этим утверждением:

«Объектно-ориентированное программирование обеспечивает уровень абстракции, который применяется одновременно к алгоритмам и данным , своего рода абстракцию, которую не обеспечивала только функциональная декомпозиция».

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

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

Если бы мы сместили условия сравнения между FP и OO от конкретных вопросов, таких как параллелизм или повторное использование, к управлению глобальной сложностью, как бы выглядела эта дискуссия?

РЕДАКТИРОВАТЬ

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

Смотрите, например, Стюарт Халлоуэй (а Clojure FP поборник) здесь говорят , что «более-спецификация типов данных» является «негативным последствием идиоматического стиля ОО» и в пользу концептуализации в AddressBook как простой вектор или карты вместо богатого объекта OO с дополнительными (не векторными и не подобными карте) свойствами и методами. (Кроме того, сторонники OO и Domain-Driven Design могут сказать, что раскрытие адресной книги в виде вектора или карты приводит к чрезмерной экспозиции инкапсулированных данных с методами, которые не имеют значения или даже опасны с точки зрения домена).


3
+1 несмотря на то, что вопрос был сформулирован довольно антагонистично, это хороший вопрос.
Mattnz

16
Как многие указывали в ответах, функциональная декомпозиция и функциональное программирование - это два разных зверя. Таким образом, вывод о том, что «это кажется довольно сложной задачей для функционального программирования», явно ошибочен, он не имеет к этому никакого отношения.
Фабио Фракасси

5
Очевидно, что знания МакКоннела в современных функциональных системах типов данных и модулях первого класса высокого порядка несколько неоднозначны. Его утверждение совершенно бессмысленно, поскольку у нас есть модули первого класса и функторы (см. SML), классы типов (см. Haskell). Это просто еще один пример того, как ОО образ мышления - это скорее религия, чем уважительная методология проектирования. И, кстати, откуда вы взяли эту вещь о параллелизме? Большинство функциональных программистов не заботятся о параллелизме.
SK-logic

6
@ SK-logic. Все, что сказал Макконнелл, заключалось в том, что «одна только функциональная декомпозиция» не обеспечивает те же средства абстракции, что и ООП, что кажется мне довольно безопасным утверждением. Нигде он не говорит, что языки FP не имеют таких мощных абстракций, как ООП. На самом деле он вообще не упоминает языки FP. Это просто интерпретация ОП.
sepp2k

2
@ sepp2k, хорошо, понятно. Но, тем не менее, очень сложная и хорошо выстроенная система структур данных и абстракций обработки может быть построена поверх ничего, кроме функциональной декомпозиции для почти чистого лямбда-исчисления - посредством моделирования поведения модулей. Нет необходимости в ОО абстракциях вообще.
SK-logic

Ответы:


13

Имейте в виду, что книга была написана более 20 лет назад. Для профессиональных программистов того времени FP не существовало - оно целиком принадлежало ученым и исследователям.

Нам нужно сформулировать «функциональную декомпозицию» в соответствующем контексте работы. Автор не имеет в виду функциональное программирование. Мы должны связать это со «структурированным программированием» и GOTOзаполненным беспорядком, который был до этого. Если ваша точка отсчета старая FORTRAN / COBOL / BASIC, в которой не было функций (возможно, если вам повезет, вы получите один уровень GOSUB), и все ваши переменные являются глобальными, то есть могут разбить вашу программу на слои функций является главным благом.

ООП является дальнейшим уточнением такого рода «функциональной декомпозиции». Вы можете не только объединять инструкции в функции, но и группировать связанные функции с данными, над которыми они работают. Результатом является четко определенный фрагмент кода, который вы можете посмотреть и понять (в идеале), не прибегая к поиску кода, чтобы выяснить, что еще может повлиять на ваши данные.


27

Я полагаю, что сторонники функционального программирования утверждают, что большинство языков FP предоставляют больше средств абстракции, чем «только функциональная декомпозиция», и фактически позволяют средства абстракций, сопоставимые по мощности с объектно-ориентированными языками. Например, можно привести классы типов Хаскелла или модули высшего порядка ML как такие средства абстракций. Таким образом, утверждение (которое, я уверен, касалось объектной ориентации или процедурного программирования, а не функционального программирования) к ним не относится.

Следует также отметить, что FP и OOP являются ортогональными понятиями и не являются взаимоисключающими. Поэтому не имеет смысла сравнивать их друг с другом. Вы можете очень хорошо сравнить «императивный ООП» (например, Java) с «функциональным ООП» (например, Scala), но приведенное вами утверждение не будет применяться к этому сравнению.


10
+1 «Функциональная декомпозиция»! = «Функциональное программирование». Первый основан на классическом последовательном кодировании с использованием ванильных структур данных без наследования, инкапсуляции и полиморфизма (или только ручного свертывания). Вторая выражает решения с использованием лямбда-исчисления. Две совершенно разные вещи.
Binary Worrier

4
Извиняюсь, но фраза «процедурного программирования» упорно не приходит в голову раньше. «Функциональная декомпозиция» для меня гораздо более показательна для процедурного программирования, чем для функционального программирования.
Двоичный беспорядок

Да, ты прав. Я действительно предполагал, что функциональное программирование предпочитает многократно используемые функции, работающие с одними и теми же простыми структурами данных (списками, деревьями, картами) снова и снова, и фактически заявляет, что это точка продажи по сравнению с ОО. См. Стюарта Хэллоуэя (сторонника Clojure FP), в котором говорится, что «чрезмерная спецификация типов данных» является «отрицательным следствием идиоматического стиля ОО», и предпочитает концептуализацию адресной книги как вектора или карты вместо более богатого объекта ОО с другими (не -векторные и не подобные карте свойства и методы.
дан

Ссылка для цитаты Стюарт Халлоуэй: thinkrelevance.com/blog/2009/08/12/...
дан

2
@dan Это может быть то, как это делается на динамически типизированном языке Clojure (я не знаю, я не использую Clojure), но я думаю, что из этого опасно делать вывод, что именно так это было сделано в FP в целом. Например, люди из Haskell, похоже, очень хорошо разбираются в абстрактных типах и сокрытии информации (хотя, возможно, не так сильно, как люди из Java).
sepp2k

7

Я считаю, что функциональное программирование чрезвычайно полезно при управлении сложностью. Однако вы склонны думать о сложности по-другому, определяя ее как функции, которые действуют на неизменяемые данные на разных уровнях, а не на инкапсуляцию в смысле ООП.

Например, я недавно написал игру на Clojure, и все состояние игры было определено в единой неизменной структуре данных:

(def starting-game-state {:map ....
                          :player ....
                          :weather ....
                          :other-stuff ....}

И основной игровой цикл можно определить как применение некоторых чистых функций к игровому состоянию в цикле:

 (loop [initial-state starting-game-state]
   (let [user-input (get-user-input)
         game-state (update-game initial-state user-input)]
     (draw-screen game-state)
     (if-not (game-ended? game-state) (recur game-state))))

Ключевая функция называется update-game, которая выполняет этап моделирования с учетом предыдущего игрового состояния и некоторого пользовательского ввода и возвращает новое игровое состояние.

Так в чем же сложность? На мой взгляд, это было сделано довольно хорошо:

  • Конечно, функция update-game выполняет много работы, но сама она создается путем составления других функций, поэтому сама по себе она довольно проста. После того, как вы пройдете несколько уровней, функции все еще будут довольно простыми, например, «добавить объект на плитку карты».
  • Конечно, состояние игры - это большая структура данных. Но опять же, он просто создается путем составления структур данных более низкого уровня. Кроме того, это «чистые данные», а не встраивание каких-либо методов или определение класса (вы можете думать об этом как об очень эффективном неизменяемом объекте JSON, если хотите), поэтому здесь очень мало шаблонов.

ООП также может управлять сложностью посредством инкапсуляции, но если сравнить это с ООП, у функционала есть несколько очень больших преимуществ:

  • Структура данных игрового состояния является неизменной, поэтому большую часть обработки можно легко выполнить параллельно. Например, совершенно безопасно иметь вызывающий отрисовку экран рисования в потоке, отличном от логики игры - они не могут влиять друг на друга или видеть несовместимое состояние. Это на удивление сложно с большим изменяемым графом объектов ......
  • Вы можете сделать снимок состояния игры в любое время. Воспроизведение тривиально (благодаря постоянным структурам данных Clojure копии практически не занимают память, поскольку большая часть данных используется совместно). Вы также можете запустить update-game, чтобы «предсказать будущее», чтобы помочь AI, например, оценить различные ходы.
  • Нигде мне не приходилось делать какие-либо сложные компромиссы, чтобы вписаться в парадигму ООП, такие как определение жесткой иерархии классов. В этом смысле функциональная структура данных ведет себя больше как гибкая система на основе прототипов.

Наконец, для людей, которые заинтересованы в более глубоком понимании того, как управлять сложностью в функциональных и ООП-языках, я настоятельно рекомендую видеоролик с основной речью Рича Хикки « Simple Made Easy» (снятый на технологической конференции Strange Loop ).


2
Я думаю, что игра - один из худших возможных примеров, демонстрирующих предполагаемые «преимущества» принудительной неизменности. В игре все постоянно движется, а это значит, что вам нужно постоянно перестраивать игровое состояние. И если все является неизменным, это означает, что вам нужно не только перестроить игровое состояние, но и все в графе, который содержит ссылку на него, или который содержит ссылку на это, и так далее, до тех пор, пока вы не переработаете все программа на 30+ FPS, с кучей оттока GC для загрузки! Там нет никакого способа получить хорошую производительность из этого ...
Мейсон Уилер

7
Конечно, игры сложны с неизменяемостью, поэтому я выбрал их, чтобы продемонстрировать, что они все еще могут работать! Однако вы будете удивлены тем, что могут сделать постоянные структуры данных - большую часть игрового состояния не нужно перестраивать, только то, что меняется. И конечно, есть некоторые накладные расходы, но это только небольшой постоянный фактор. Дайте мне достаточно ядер, и я побью ваш однопоточный игровой движок C ++ .....
mikera

3
@Mason Wheeler: На самом деле, это можно получить практически равны (так хорошо , как с мутацией) производительность с неизменяемыми объектами, без особого GC вообще. Хитрость в Clojure заключается в использовании постоянных структур данных : они неизменяемы для программиста, но на самом деле изменчивы под капотом. Лучшее обоих миров.
Joonas Pulakka

4
@quant_dev Больше ядер дешевле, чем более качественных ... escapistmagazine.com/news/view/…
deworde

6
@quant_dev - это не оправдание, это математический и архитектурный факт, что вам лучше нести постоянные издержки, если вы можете восполнить это, масштабируя свою производительность почти линейно с количеством ядер. Причина, по которой функциональные языки в конечном итоге обеспечат превосходную производительность, заключается в том, что мы подошли к концу линии для одноядерной производительности, и все это будет связано с параллелизмом и параллелизмом в будущем. функциональные подходы (и неизменность в частности) важны для выполнения этой работы.
Микера

3

«Объектно-ориентированное программирование обеспечивает уровень абстракции, который применяется одновременно к алгоритмам и данным, своего рода абстракцию, которую не обеспечивала только функциональная декомпозиция».

Одной только функциональной декомпозиции недостаточно для создания какого-либо алгоритма или программы: вам также необходимо представлять данные. Я думаю, что приведенное выше утверждение неявно предполагает (или, по крайней мере, его можно понять так), что «данные» в функциональном случае имеют самый элементарный вид: просто списки символов и ничего больше. Программирование на таком языке, очевидно, не очень удобно. Однако многие, особенно новые и современные, функциональные (или мультипарадигмальные) языки, такие как Clojure, предлагают богатые структуры данных: не только списки, но и строки, векторы, карты и наборы, записи, структуры - и объекты! - с метаданными и полиморфизмом.

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


1
Я где-то слышал фразу «ОО в целом, ФП в малом» - думаю, Майкл Фезерс цитировал ее. Это означает, что FP может быть полезен для отдельных частей большой программы, но в целом это должно быть ОО.
дан

Кроме того, вместо использования Clojure для всего, даже для вещей, которые более четко выражены в более традиционном синтаксисе OO, как насчет использования Clojure для битов обработки данных, где он чище, и использования Java или какого-либо другого языка OO для других битов. Программирование полиглота вместо многопарадигмального программирования на одном языке для всех частей программы. (Вроде как, как большинство веб-приложений используют SQL и OO для разных слоев.)?
дан

@ Дан: Используйте любой инструмент, который подходит для работы лучше всего. В программировании полиглотов решающим фактором является удобная связь между языками, и Clojure и Java вряд ли могли бы играть лучше вместе . Я полагаю, что самые существенные программы Clojure используют по крайней мере некоторые кусочки стандартных библиотек Java JDK здесь и там.
Joonas Pulakka

2

Изменчивое состояние является корнем большинства сложностей и проблем, связанных с программированием и программным / системным проектированием.

ОО охватывает изменяемое состояние. FP не терпит изменчивого состояния.

И у ОО, и у ФП есть свои применения и приятные места. Выбирать мудро. И помните пословицу: «Закрытия - это объекты бедняков. Объекты - это замыкания бедняков».


3
Я не уверен, что ваше первое утверждение верно. Корень "большинства" из сложностей? В программировании, которое я делал или видел, проблема не столько в изменчивом состоянии, сколько в недостатке абстракции и переизбытке деталей в коде.
дан

1
@ Дан: Интересно. На самом деле я видел много противоположного: проблемы возникают из-за чрезмерного использования абстракции, что затрудняет как понимание, так и, при необходимости, исправление деталей того, что происходит на самом деле.
Мейсон Уилер

1

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

Давайте рассмотрим очень простой пример. Допустим, Oracle решил, что Java Strings должен иметь обратный метод, и вы написали следующий код.

String x = "abc";
StringBuffer y = new StringBuffer(x);
y.reverse();
x.reverse();
x.toString().equals(y.toString());

что оценивает последняя строка? Вам нужны специальные знания о классе String, чтобы знать, что это будет иметь значение false.

Что делать, если я сделал свой собственный класс WuHoString

String x = "abc";
WuHoString y = new WuHoString(x);
y.reverse();
x.reverse();
x.toString().equals(y.toString())

Невозможно знать, к чему относится последняя строка.

В стиле функционального программирования это будет написано так:

String x;
equals(toString(reverse(x)), toString(reverse(WuHoString(x))))

и это должно быть правдой.

Если одну функцию в одном из самых базовых классов так сложно рассуждать, то возникает вопрос: увеличилась или уменьшилась сложность представления об изменчивых объектах?

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


3
Немного забавно, что вы говорите, что ОО-языки не созданы для неизменяемых объектов, а затем позже используете пример со строками (которые являются неизменяемыми в большинстве ОО-языков, включая Java). Также я должен отметить, что существуют ОО (или, скорее, мультипарадигмальные) языки, которые разработаны с упором на неизменяемые объекты (например, Scala).
sepp2k

@ sepp2k: привыкнуть к этому. Сторонники FP всегда разбрасывают причудливые надуманные примеры, которые не имеют ничего общего с реальным кодированием. Это единственный способ сделать так, чтобы основные концепции FP, такие как принудительная неизменность, выглядели хорошо.
Мейсон Уилер

1
@ Мейсон: А? Разве лучший способ придать неизменности внешнему виду - это сказать: «Java (и C #, python и т. Д.) Используют неизменяемые строки, и это прекрасно работает»?
sepp2k

1
@ sepp2k: Если неизменяемые строки работают так хорошо, почему классы стилей StringBuilder / StringBuffer продолжают появляться повсюду? Это просто еще один пример инверсии абстракции на вашем пути.
Мейсон Уилер

2
Многие объектно-ориентированные языки позволяют создавать неизменяемые объекты. Но концепция привязки методов к классу действительно обескураживает ее с моей точки зрения. Пример String на самом деле не надуманный пример. Всякий раз, когда я вызываю какой-либо метод в Java, я рискую, чтобы мои параметры не изменялись в рамках этой функции.
WuHoUnited

0

Я думаю, что в большинстве случаев классическая абстракция ООП не покрывает сложности параллелизма. Поэтому ООП (в своем первоначальном значении) не исключает FP, и поэтому мы видим такие вещи, как scala.


0

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

У Haskell (и похожего языка, я думаю) есть совершенно другой ответ: алгебраические типы данных. Алгебраический тип данных похож на Cструктуру, но с большим количеством опций. Эти типы данных обеспечивают абстракцию, необходимую для моделирования данных; функции обеспечивают абстракцию, необходимую для моделирования алгоритмов. Классы типов и другие расширенные возможности обеспечивают еще более высокий уровень абстракции над обоими.

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

data TPLValue = Null
              | Number Integer
              | String String
              | List [TPLValue]
              | Function [TPLValue] TPLValue
              -- There's more in the real code...

Это очень наглядно говорит о том, что TPLValue (любое значение на моем языке) может быть Nullили Numberсо Integerзначением или даже Functionсо списком значений (параметров) и конечным значением (телом). ).

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

Кроме того, я могу использовать свои собственные классы типов, когда мне нужно указать поведение определенных типов (включая те, которые я сам не реализовал). Например, у меня есть Extractableкласс типов, который позволяет мне написать функцию, которая принимает TPLValueи возвращает соответствующее нормальное значение. Таким образом, extractможно преобразовать a Numberв a Integerили a Stringв a, Stringесли Integerи Stringявляются экземплярами Extractable.

Наконец, основная логика моей программы заключается в нескольких функциях, таких как evalи apply. Это действительно ядро ​​- они берут TPLValues и превращают их в больше TPLValues, а также обрабатывают состояние и ошибки.

В целом, абстракции, которые я использую в своем коде на Haskell, на самом деле более мощные, чем те, которые я использовал бы в языке ООП.


Да, надо любить eval. «Эй, посмотри на меня! Мне не нужно писать собственные дыры в безопасности; у меня есть уязвимость, связанная с выполнением произвольного кода, встроенная прямо в язык программирования!» Сопоставление данных с кодом является основной причиной одного из двух самых популярных классов уязвимостей безопасности всех времен. Каждый раз, когда вы видите, что кто-то взломан из-за атаки с использованием SQL-инъекции (помимо всего прочего), это потому, что некоторые программисты не знают, как правильно отделить данные от кода.
Мейсон Уилер

evalне сильно зависит от структуры Lisp - вы можете использовать такие evalязыки, как JavaScript и Python. Настоящая сила заключается в написании макросов, которые в основном являются программами, которые работают с такими программами, как данные, и выводят другие программы. Это делает язык очень гибким и легко создает мощные абстракции.
Тихон Джелвис

3
Да, я слышал, что "макросы потрясающие" говорили много раз раньше. Но я никогда не видел фактического примера макроса Lisp, который делает что-то, что 1) практично, и что-то, что вы на самом деле хотели бы сделать в реальном коде и 2) не может быть выполнено так же легко на любом языке, который поддерживает функции.
Мейсон Уилер

1
@MasonWheeler короткое замыкание and. короткое замыкание or. let, let-rec, cond, defn, Ничто из этого не может быть реализовано с помощью функций на языках соответствующего порядка. for(список пониманий). dotimes, doto,

1
@MattFenwick: Хорошо, я действительно должен был добавить третий пункт к моим двум выше: 3) еще не встроен ни в один из нормальных языков программирования. Потому что это единственные действительно полезные примеры макросов, которые я когда-либо видел, и когда вы говорите: «Эй, посмотрите на меня, мой язык настолько гибок, что я могу реализовать свое собственное короткое замыкание and!» Я слышу: «Эй, посмотри на меня, мой язык настолько искажен, что даже с коротким замыканием не приходит, andи мне нужно заново изобретать колесо для всего
Мейсон Уилер

0

Насколько я вижу, цитируемое предложение больше не имеет никакой юридической силы.

Современные ОО-языки не могут абстрагироваться от типов, тип которых не *, то есть типы с более высоким родом неизвестны. Их система типов не позволяет выразить идею «некоторого контейнера с элементами Int, который позволяет отобразить функцию над элементами».

Следовательно, эта основная функция, как Haskells

fmap :: Functor f => (a -> b) -> f a -> f b 

не может быть легко написано на Java *), например, по крайней мере, не безопасным способом. Следовательно, чтобы получить базовую функциональность, вы должны написать множество шаблонов, потому что вам нужно

  1. метод применения простой функции к элементам списка
  2. метод для применения одной и той же простой функции к элементам массива
  3. метод для применения той же простой функции к значениям хеша,
  4. .... поставил
  5. .... дерево
  6. ... 10. модульные тесты для того же

И, тем не менее, эти пять методов в основном представляют собой один и тот же код, один или несколько. Напротив, в Хаскеле мне понадобится:

  1. Экземпляр Functor для списка, массива, карты, множества и дерева (в основном предопределенный или может быть автоматически получен компилятором)
  2. простая функция

Обратите внимание, что это не изменится в Java 8 (просто можно проще применять функции, но тогда точно возникнет описанная выше проблема. Пока у вас даже нет функций более высокого порядка, вы, скорее всего, даже не в состоянии понять, для чего хороши более высокие типы.)

Даже новые ОО-языки, такие как Цейлон, не имеют более высокодобренных типов. (В последнее время я спрашивал Гэвина Кинга, и он сказал мне, что это сейчас не важно.) Не знаю, как насчет Котлина.

*) Если честно, у вас может быть интерфейс Functor с методом fmap. Плохо то, что вы не можете сказать: эй, я знаю, как реализовать fmap для библиотечного класса SuperConcurrentBlockedDoublyLinkedDequeHasMap, дорогой компилятор, пожалуйста, примите, что с этого момента все SuperConcurrentBlockedDoublyLinkedDequeHasMaps являются функторами.


FTR: программа проверки Цейлона и JavaScript бакэнда в настоящее время сделать поддержку более руками типов (а также более высокими ранговыми типов). Это считается «экспериментальной» функцией. Тем не менее, наше сообщество изо всех сил пыталось найти практические приложения для этой функциональности, поэтому остается открытым вопрос, будет ли это когда-либо «официальной» частью языка. Я бы ожидать , что она будет поддержана Java бэкенд на каком - то этапе.
Гэвин Кинг

-2

Любой, кто когда-либо программировал в dBase, знал, насколько полезны однострочные макросы для создания кода многократного использования. Хотя я не программировал на Лиспе, я читал от многих других, которые клянутся макросами времени компиляции. Идея внедрения кода в ваш код во время компиляции используется в простой форме в каждой C-программе с директивой include. Поскольку Лисп может сделать это с помощью программы на Лиспе, а Лисп обладает высокой отражающей способностью, вы получаете гораздо более гибкие включения.

Любой программист, который просто взял бы произвольную текстовую строку из Интернета и передал ее в свою базу данных, не является программистом. Точно так же любой, кто позволил бы «пользовательским» данным автоматически становиться исполняемым кодом, явно глуп. Это не означает, что позволить программам манипулировать данными во время выполнения, а затем выполнять их как код - плохая идея. Я полагаю, что эта техника будет незаменимой в будущем, когда в большинстве программ будет «умный» код. Вся «проблема с данными / кодом» или нет - это вопрос безопасности на языке.

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


2
Добро пожаловать в Программисты. Пожалуйста, постарайтесь смягчить риторику в своем ответе и подкрепите некоторые из ваших утверждений внешними ссылками.

1
Любой программист, который позволил бы пользовательским данным автоматически становиться исполняемым кодом, очевидно, неосведомлен . Не глупо. Делать это таким образом часто легко и очевидно, и если они не знают, почему это плохая идея и что существует лучшее решение, вы не можете винить их за это. (Любой, кто продолжает делать это после того, как его учили, что есть лучший способ, тем не менее, явно глуп).
Мейсон Уилер,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.