nicla driven development

Техники декларативного программирования

Отрывок из книги Concepts, Techniques, and Models of Computer Programming


Пожалуйста... нарисуй мне барашка!

  • Антуан де Сент-Экзюпери. Маленький принц

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

  • The Craft of Prolog, Richard O’Keefe

Декларативная операция обладает следующими свойствами:

  • независима (independent) ни от какого внешнего состояния,
  • без состояния (stateless) - не имеет внутреннего состояния, которое сохраняется между вызовами
  • предопределена (deterministic)- при одинаковых аргументах всегда дает одинаковый результат

Почему декларативное программирование важно:

  • Композиционность - декларативная программа состоит из компонентов, каждый из которых может быть написан и проверен отдельно от остальных, а также без учета собственной истории (см. stateless)
  • Простота понимания - программы написанные с использованием декларативной модели часто проще понимать, (чем написанные с использованием других более выразительных моделей) поскольку они оперируют только значениями, и к ним применимы алгебраические и логические приемы.

Два этих свойства важны, как для программирования в малом (in small), так и для программирования в масштабе (in large). Было бы чудесно, если бы все программы можно было легко написать с использованием декларативной модели. К сожалению, это не возможно. Декларативная модель хорошо подходит для определенного типа задач и плохо для других.

Давайте определим компонент как фрагмент кода с определенными входными данными и результатом. Компонент, в свою очередь, может быть составлен из других более простых компонентов. Например, функция может быть таким компонентом. Программа, таким образом, это компонент самого верхнего уровня в иерархии компонентов. Самый нижний слой компонентов это примитивы предоставляемые средой исполнения.

В декларативной модели компонент полностью определяется входными и выходными данными. Такие компоненты можно понять сами по себе, без необходимости понимать остальную систему. Таким образом, усилия для понимания программы являются суммой усилий для понимания каждого из компонентов.

Если компоненты более интимно связанны с остальной системой, их сложно понимать в отрыве от нее. И в целом разобраться в программе гораздо сложнее (в среднем как произведение количества компонентов). Программы с большим количество тесно связанных компонентов понимать очень сложно или невозможно. Примером такой тесной связи можно считать конкурентные программы с общим состоянием (shared state).

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

Стандартное правило алгебры говорит "равное может быть заменено равным". В программировании это называется referential transparency. Она очень упрощает понимание программы. Например если f(x)=2*x, то мы можем заменить все вхождения f(x) на ее определение 5*f(x) => 5*2*x.

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

Интуитивно декларативность это когда вы говорите что сделать (те результат вычислений), а не как это сделать (алгоритм, необходимый для достижения результата). Декларативность можно разделить на описательную и программную.

  • описательная: декларативная программа просто является структурой данных (HTML, XML, CSS ...)
  • программная: полный по Тюрингу язык...

Так же есть два способа взглянуть на декларативность - definitional and observational точки зрения.

  • Декларативность по определению (definitional) - это когда декларативность есть свойство реализации компонентов, гарантирующее что любая их комбинация дает снова декларативную модель
  • Видимая (observational) декларативность - это когда компонент ведет себя как декларативный (те имеет декларативный интерфейс - independent, stateless & deterministic), но реализация его может быть иной

Два стиля декларативного программирования стали популярны - это функциональный и логический. В случае функционального программирования мы определяем компонент как математическую функцию (Haskell, Standard ML). В логическом программировании мы определяем компонент как логическое отношение (logical relation) (Prolog & Mercury).

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

Язык Спецификаций

Пропоненты декларативного программирования часто заявляют что оно позволяет им не думать о реализации поскольку все превращается в спецификацию. Спецификация оказывается программой только в формальном смысле. На практике декларативные программы больше похожи на другие программы: они требуют алгоритмов, структур данных, структурирования, определенного порядка операций. Это происходит поскольку декларативные языки могут использовать только те математические абстракции, которые могут быть эффективно реализованы. Существует компромисс между выразительностью и эффективностью. Декларативные программы обычно гораздо длиннее чем могли бы быть спецификации. И различие между спецификацией и реализацией до сих пор присутствует.

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

...

04 Feb 2014 niquola


comments powered by Disqus