На этом этапе вы, несомненно, слышали об императивном программировании и декларативном программировании. Возможно, вы даже искали, что на самом деле означают эти термины.
К сожалению, вы, вероятно, встретили определение, подобное этому: «Вы знаете, императивное программирование - это как« как »вы что-то делаете, а декларативное программирование больше похоже на« что »вы делаете или что-то в этом роде».
Это определение имеет смысл, если вы действительно знаете разницу между императивом и декларативностью, но вы этого не знаете, поэтому вы задали этот вопрос в первую очередь. Это все равно, что пытаться ответить: «Что было раньше, курица или яйцо?» за исключением того, что все, кажется, думают, что курица любит, но вы даже не любите яйца, и вы сбиты с толку.
Объедините это разочарование с бессмысленным употреблением слова декларативный, чтобы в основном означать хорошо, и внезапно ваш синдром самозванца превратился в чечетку на вашей уверенности, и вы поймете, что вам даже не нравится программировать.
Но не волнуйся, друг. Я не знаю, что такое монада, поэтому, надеюсь, этот пост поможет вам понять, что декларативность - это больше, чем просто «легко рассуждать» и «хорошо».
Самая сложная часть этой темы, как заметил Меррик: Это одна из тех вещей, о которых вы догадываетесь, но не можете объяснить.
Я разговаривал со многими разработчиками, и мне кажется, что больше всего помогает сочетание метафор с реальными примерами кода. Так что пристегнитесь, потому что я собираюсь проповедовать.
Давайте вернемся к первоначальному определению, над которым я высмеивал: «Императивное программирование - это« как »вы что-то делаете, а декларативное программирование больше похоже« что »вы делаете». На самом деле здесь спрятана НЕКОТОРАЯ хорошая информация. Давайте сначала рассмотрим достоинства этого определения, вырвав его из контекста программирования и посмотрев на пример из «реальной жизни».
Вы решаете, что потратили слишком много времени на споры о «Усталости от JavaScript» ™ и реактивном функциональном программировании, и ваш муж заслуживает приятного свидания. Вы решили пойти в Red Lobster, поскольку в последнее время много слушаете Бейонсе. 👑🐝. Вы приезжаете в Red Lobster, подходите к стойке регистрации и говорите…
Повелительный подход (КАК): я вижу, что таблица, расположенная под знаком Gone Fishin, пуста. Мы с мужем собираемся пойти туда и сесть.
Декларативный подход (ЧТО): Таблица на двоих, пожалуйста.
Императивный подход связан с тем, КАК вы на самом деле получите место. Вам нужно перечислить шаги, чтобы показать, КАК вы собираетесь получить стол. Декларативный подход больше касается того, ЧТО вы хотите - стола на двоих.
"Ok." - твой мозг
Больше метафор!
Я задам вам вопрос. Я хочу, чтобы вы подумали как об императивном, так и о декларативном ответе.
«Я принадлежу Wal-Mart. Как мне отсюда добраться до твоего дома? »
Повелительный ответ: выйдите из северного выхода с парковки и поверните налево. Двигайтесь по автомагистрали I-15 на юг, пока не дойдете до съезда с шоссе Bangerter. Сверните направо с выезда, как будто собираетесь в Ikea. Идите прямо и на первом светофоре поверните направо. Продолжайте движение на следующий светофор, затем поверните налево. Мой дом № 298.
Декларативный ответ: Мой адрес: 298 West Immutable Alley, Draper Utah 84020.
Независимо от того, как я доберусь до вашего дома, действительно имеет значение машина, на которой я езжу. Я собираюсь водить автомобиль с обязательным ручным переключением передач или декларативным автомобилем с автоматической коробкой передач. Достаточно метафор?
Прежде чем мы углубимся в код, важно понять, что многие декларативные подходы имеют своего рода императивный слой абстракции. Взгляните на все наши примеры:
Декларативный ответ сотруднику Red Lobster предполагает, что сотрудник Red Lobster знает все необходимые шаги, чтобы заставить нас сесть за стол. Знание адреса предполагает, что у вас есть какой-то GPS, который знает, как добраться до вашего дома.
У автомобиля с автоматической коробкой передач есть своего рода слой абстракции над переключением передач.
Это было осознание, которое действительно заставило меня поразить меня, поэтому я повторю: многие (если не все) декларативные подходы имеют своего рода основную императивную абстракцию.
Если это предложение имеет смысл, у вас все отлично!
Теперь мы попытаемся совершить прыжок из метафорической счастливой страны в мир реальных кодов. Чтобы сделать скачок более изящным, давайте посмотрим на некоторые «языки» программирования, которые по своей сути декларативны, в сравнении с теми, которые по своей природе императивны.
Обязательные: C, C ++, Java
Декларативные: SQL, HTML
(Может быть) Смешивание: JavaScript, C #, Python
Подумайте о своем типичном примере SQL или HTML,
SELECT * FROM Users WHERE Country=’Mexico’; <article> <header> <h1>Declarative Programming</h1> <p>Sprinkle Declarative in your verbiage to sound smart</p> </header> </article>
Взглянув на оба примера, вы получите очень четкое представление о том, что происходит. Оба они декларативны. Их волнует, ЧТО вы хотите сделать, а не КАК вы этого хотите.
Вы описываете, чего пытаетесь достичь, но не инструктируете, как это сделать. Реализация выбора всех пользователей, проживающих в Мексике, была отвлечена от вас. Вас не волнует, как веб-браузер анализирует вашу статью и отображает ее на экране. Ваше ЧТО - это мексиканские пользователи и новый заголовок и абзац на вашем веб-сайте.
Все идет нормально. Давайте рассмотрим более практические примеры JavaScript.
Я хочу, чтобы вы представили, что вы сейчас на техническом собеседовании, а я - интервьюер. Откройте консоль и ответьте на следующие вопросы.
- Напишите функцию с именем double, которая принимает массив чисел и возвращает новый массив после удвоения каждого элемента в этом массиве. двойной ([1,2,3]) - ›[2,4,6]
- Напишите функцию с именем add, которая принимает массив и возвращает результат сложения каждого элемента в массиве. добавить ([1,2,3]) - ›6
- Используя jQuery (или обычный JavaScript), добавьте обработчик события click к элементу с идентификатором «btn». При нажатии переключите (добавьте или удалите) «выделить», а также изменить текст на «Добавить выделение» или «Удалить выделение» в зависимости от текущего состояния элемента.
Давайте посмотрим на наиболее распространенные подходы к этим проблемам, которые также являются императивными подходами.
function double (arr) { let results = [] for (let i = 0; i < arr.length; i++){ results.push(arr[i] * 2) } return results }
2.
function add (arr) { let result = 0 for (let i = 0; i < arr.length; i++){ result += arr[i] } return result }
3.
$("#btn").click(function() { $(this).toggleClass("highlight") $(this).text() === 'Add Highlight' ? $(this).text('Remove Highlight') : $(this).text('Add Highlight') })
Изучив, что общего у всех трех императивных примеров, мы сможем лучше определить, что на самом деле делает их императивными.
- Наиболее очевидная общность заключается в том, что они описывают КАК что-то делать. В каждом примере мы либо явно перебираем массив, либо явно описываем шаги по реализации желаемой функциональности.
- Это может быть не так очевидно, если вы не привыкли мыслить «декларативно» или, точнее, «функционально». В каждом примере мы изменяем некоторую часть состояния (если вы не знакомы с термином «состояние», это, по сути, информация о чем-то, хранящемся в памяти, что должно звучать очень похоже на переменные). В первых двух примерах мы создаем переменную с именем результаты, а затем мы постоянно их модифицируем. В третьем примере у нас нет никаких переменных, но у нас все еще есть состояние, живущее в самой DOM - затем мы изменяем это состояние в DOM.
- Это немного субъективно, но для меня приведенный выше код не очень удобочитаем. Я не могу просто взглянуть на код и понять, что происходит. Мой мозг должен пройти через код так же, как это сделал бы интерпретатор, но с учетом контекста, в котором живет код (еще один негативный фактор изменяемых данных).
Ладно, хватит кода. Давайте теперь рассмотрим несколько декларативных примеров. Цель - исправить все проблемы сверху. Таким образом, каждый пример должен описывать, ЧТО происходит, не может изменять состояние и должен быть легко читаемым.
1.
function double (arr) { return arr.map((item) => item * 2) }
2.
function add (arr) { return arr.reduce((prev, current) => prev + current, 0) }
3.
<Btn onToggleHighlight={this.handleToggleHighlight} highlight={this.state.highlight}> {this.state.buttonText} </Btn>
Намного лучше
Обратите внимание, что в первых двух примерах мы используем встроенные в JavaScript методы map и reduce. Это восходит к тому, о чем мы неоднократно говорили в этой статье, что большинство декларативных решений - это абстракция над некоторой императивной реализацией.
В каждом примере мы описываем ЧТО мы хотим, а не КАК (мы не знаем, КАК реализованы map и reduce, нам также все равно). Мы не изменяем ни одно состояние. Все мутации абстрагируются внутри map и reduce. Кроме того, он более читабелен (если вы, конечно, привыкнете к map и reduce).
А что насчет №3? Ну, я немного схитрил и использую React - но учтите, что все три обязательные ошибки все еще исправлены. Настоящая прелесть React в том, что вы можете создавать декларативные пользовательские интерфейсы. Глядя на наш компонент Btn, я могу легко понять, как будет выглядеть пользовательский интерфейс. Еще одно преимущество состоит в том, что вместо состояния, живущего в DOM, оно живет в самом компоненте React.
Еще одно преимущество декларативного кода, о котором меньше говорят, заключается в том, что ваша программа может быть независимой от контекста. Это означает, что, поскольку ваш код связан с конечной целью, а не с шагами, которые необходимо предпринять для достижения этой цели, один и тот же код может использоваться в разных программах и работать нормально.
Взгляните на все три приведенных выше примера. Мы можем использовать как функции, так и компоненты в любой программе, какой захотим. Они программные агностики. Это сложно сделать с императивным кодом, потому что часто по определению императивный код зависит от контекста текущего состояния.
Одна вещь, в которой я не стал заходить слишком далеко, - это то, что функциональное программирование является подмножеством декларативного программирования. Если вы еще этого не сделали, я настоятельно рекомендую поближе познакомиться с методами функционального программирования на JavaScript. Начните с .map, .reduce, .filter и двигайтесь дальше.
Скорее всего, нет более низкого результата для улучшения вашей кодовой базы, чем повышение ее функциональности.
С учетом всего вышесказанного, одна из моих любимых вещей - найти в Интернете определения, в которых создатель этого определения больше заботился о том, чтобы звучать умно, чем о предоставлении полезного, потребляемого определения. Императив против декларативного имеет ТАКОЕ много хороших примеров. Наслаждаться!
Декларативное программирование - это «акт программирования на языках, которые соответствуют ментальной модели разработчика, а не операционной модели машины».
Декларативное программирование - это программирование с объявлениями, то есть декларативными предложениями.
В декларативном свойстве может существовать только один возможный набор операторов, который может выражать каждую конкретную модульную семантику. Императивное свойство является двойственным, когда семантика несовместима при композиции и / или может быть выражена с помощью вариаций наборов операторов.
Декларативные языки контрастируют с императивными языками, которые определяют явное манипулирование внутренним состоянием компьютера; или процедурные языки, которые определяют явную последовательность шагов, которым нужно следовать.
В информатике декларативное программирование - это парадигма программирования, которая выражает логику вычисления без описания его потока управления.
Первоначально опубликовано на tylermcginnis.com
Следите за новостями Тайлера МакГинниса в Twitter.