Принципы разработки программ для решения прикладных задач императивное программирование

Обновлено: 07.07.2024

Императивное программирование что такое и зачем

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

Также посмотрите статью «Что такое метапрограммирование», тоже очень интересно.

Императивное программирование:

Императивное программирование описывает расчет с помощью последовательности команд и определяет точную процедуру ( алгоритм ) решения задачи.

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

Основным методом императивного программирования является процедурное программирование, поэтому эти термины часто путают.

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

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

Аппаратное обеспечение, такое как повар / ассемблер, затем выполняет команду за командой в точности, как это соответствует императивному подходу.

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

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

Первыми императивными языками программирования были машинные языки отдельных компьютеров.

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

Первым языком, устраняющим барьеры машинного кода для создания сложных программ, был FORTRAN, созданный Джоном Бэкусом в IBM в 1954 году.

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

Следующие два десятилетия принесли с собой другие важные языки программирования более высокого уровня . К концу 1950-х и 1960-х годов появился язык АЛГОЛ, упростивший программирование математических алгоритмов.

В семидесятых годах он был Никлаус Вирт разработан язык Паскаль и Деннис Ритчи (работают в Bell Labs ) языке C . Затем Вирт занялся языками Модула-2 и Оберон . Первый объектный язык был создан в конце 1960-х годов,Simula.

Для нужд Министерства обороны США в 1978 году, после четырех лет обобщения требований, Джин Ичбиа и команда Honeywell приступили к разработке языка Ada. Спецификация была впервые опубликована в 1983 году и пересматривалась в 1995 и 2005/6 гг.

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

За последние два десятилетия двадцатого века их было создано значительное количество. В 1980 годе Palo Alto Research Center Xerox опубликовала Smalltalk -80 языка, первоначально задуманный Алан Кей в 1969 г.

Деление:

В конечном итоге императивное программирование можно разделить на три группы.

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

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

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

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

Основные типы команд:

В императивном программировании используются три основные группы команд.

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

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

Циклы позволяют повторять последовательность команд несколько раз подряд. Затем можно точно определить количество повторений или последовательность может повторяться до тех пор, пока указанное условие не изменится.

Команды ветвления позволяют выполнять определенную часть команд только при соблюдении соответствующего условия.

В противном случае этот раздел пропускается, и выполнение следующих сразу же команд продолжается.

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

Отличия в противоположном подходе:

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

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

С другой стороны, при императивном подходе программист может оптимизировать программу так, как ему нужно.

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

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

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

Вывод:

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


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

Ладно. Введение это очень весело, но вы его все равно не читаете, так что кому интересно — добро пожаловать под кат!

Императивное программирование



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

Это были машинные коды, языки ассемблера и ранние высокоуровневые языки, вроде Fortran.

Ключевые моменты:

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

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

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

В совсем высокоуровневых (таких как Python, если на нем программировать императивно) состояние ограничивается лишь переменными, а команды могут представлять собой комплексные операции, которые на ассемблере занимали бы сотни строк.

Основные понятия:

Порожденные понятия:

— Присваивание
— Переход
— Память
— Указатель

Языки поддерживающие данную парадигму:

Как основную:

— Языки ассемблера
— Fortran
— Algol
— Cobol
— Pascal
— C
— C++
— Ada

Как вспомогательную:

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

Структурное программирование



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

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

Языками-первопроходцами в этой парадигме были Fortran, Algol и B, позже их приемниками стали Pascal и C.

Ключевые моменты:

Эта парадигма вводит новые понятия, объединяющие часто используемые шаблоны написания императивного кода.

В структурном программировании мы по прежнему оперируем состоянием и инструкциями, однако вводится понятие составной инструкции (блока), инструкций ветвления и цикла.

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

Иногда goto все-же делает код читабельнее, благодаря чему он до сих пор широко используется, несмотря на все заявления его противников.

Основные понятия:

— Блок
— Цикл
— Ветвление

Языки поддерживающие данную парадигму:

Как основную:

— C
— Pascal
— Basic

Как вспомогательную:

Поддерживают частично:
— Некоторые макроассемблеры (через макросы)

Опять-же большая часть современных языков поддерживают структурную парадигму.

Процедурное программирование



Опять-же возрастающая сложность программного обеспечения заставила программистов искать другие способы описывать вычисления.

Собственно еще раз были введены дополнительные понятия, которые позволили по-новому взглянуть на программирование.

Этим понятием на этот раз была процедура.

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

Ключевые моменты:

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

В современном программировании процедура может иметь несколько точек выхода (return в C-подобных языках), несколько точек входа (с помощью yield в Python или статических локальных переменных в C++), иметь аргументы, возвращать значение как результат своего выполнения, быть перегруженной по количеству или типу параметров и много чего еще.

Основные понятия:

Порожденные понятия:

— Вызов
— Аргументы
— Возврат
— Рекурсия
— Перегрузка

Языки поддерживающие данную парадигму:

Как основную:

— C
— C++
— Pascal
— Object Pascal

Как вспомогательную:

Поддерживают частично:
— Ранний Basic

Стоит отметить, что несколько точек входа из всех этих языков поддерживаются только в Python.

Модульное программирование



Который раз увеличивающаяся сложность программ заставила разработчиков разделять свой код. На этот раз процедур было недостаточно и в этот раз было введено новое понятие — модуль.

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

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

Благодаря модулям впервые в программировании появилась серьезная инкапсуляция — возможно использовать какие-либо сущности внутри модуля, но не показывать их внешнему миру.

Ключевые моменты:

Модуль — это отдельная именованная сущность программы, которая объединяет в себе другие программные единицы, близкие по функциональности.

Например файл List.mod включающий в себя класс List
и функции для работы с ним — модуль.

Папка Geometry, содержащая модули Shape, Rectangle и Triangle — тоже модуль, хоть и некоторые языки разделяют понятие модуля и пакета (в таких языках пакет — набор модулей и/или набор других пакетов).

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

Основные понятия:

Порожденные понятия:

Языки поддерживающие данную парадигму:

Как основную:

— Haskell
— Pascal
— Python

Как вспомогательную:

Поддерживают частично:
— C/C++

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

Вместо заключения

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

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

Или насколько неверным было мое представление о React

Feb 11, 2018 · 4 min read


Если вы читали документацию React, вы, вероятно, заметили, что React является декларативным. Обычно я пропускаю такого рода инфорамцию— согласен, не очень хорошая привычка. (Дайте мне скорее примеры кода!) Но как и всякий, кто начал изучать React сразу после колледжа, я часто думал о задачах неправильно.

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

Согласно этой и этой информации:

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

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

Прежде чем я зайду слишком далеко, хочу подчеркнуть, что нет ничего плохого в любом из этих подходов. У каждого есть сильные и слабые стороны, но один подход — всегда правильно. Например, декларативное программирование может привести к меньшему прямому контролю, что может быть неверным для таких приложений, как встроенные системы, где «правильный ответ, полученный слишком поздно, становится неправильным ответом».

Хорошо, вот метафора.

Декларативное программирование — это как попросить вашего друга нарисовать пейзаж. Тебе все равно, как он рисует, это зависит от него.

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

Ладно, ладно, вот несколько примеров кода. У нас есть кнопка, которая меняет цвет при нажатии. Я начну с императивного примера:

И пример нашего декларатвного React:

Возможно, различия незначительны. У нас по-прежнему есть логика, которая говорит: если красный, значит синий, но есть одна огромная разница. Пример c React никогда не затрагивает элемент. Он просто объявляет, что элемент должен отображаться с учетом нашего текущего состояния (далее — state). Он фактически не манипулирует самим DOM.

Использование прямого манипулирования DOM является ошибкой, которую я часто делал, когда впервые начал работать с React. Я заметил, что это тоже является проблемой для разработчиков, у которых большой опыт в jQuery.

При написании React зачастую нужно думать не о том, как вы хотите достичь результата, а об внешнем виде компонента с его новым state. Это заставляет нас хорошо контролировать поток, где state проходит через серию предсказуемых и воспроизводимых мутаций. Это относится не только к компонентам, но и к state самого приложения. Библиотеки, такие как Redux, могут помочь реализовать этот архитектурный подход, но они не обязательны для достижения этой цели.

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

Я либо допустил, либо позволил допустить все эти ошибки в коде, над которым работал. Это всего лишь советы.


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

Роман Меньшиков, ведущий системный программист компании «Аэродиск»

Декларативное программирование — это парадигма программирования, в которой задаётся спецификация решения задачи: описывается, что представляет собой проблема и ожидаемый результат, но без описания способа достижения этого результата. Зачастую декларативные программы не используют понятия состояния и, в частности, не содержат переменных и операторов присваивания, обеспечивая ссылочную прозрачность. К подвидам декларативного программирования часто относят и функциональное программирование. Декларативные компьютерные языки часто не полны по Тьюрингу, так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию.

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

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

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

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

Михаил Козин, руководитель отдела разработки ECM «Т1 Консалтинг»

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

Декларативное программирование — это парадигма, при которой описывается желаемый результат, без составления детального алгоритма его получения. В пример можно привести HTML и SQL. При создании HTML мы с помощью тегов описываем, какую хотим получить страничку в браузере, а не то, как нарисовать на экране заголовок статьи, оглавление и текст. В SQL, если нам нужно посчитать количество сотрудников с фамилией «Сидоров», мы напишем SELECT count(*) FROM employee WHERE last_name = 'Сидоров'; . Тут ничего не сказано про то, в каком файле или области памяти находятся данные по сотрудникам, как именно выбрать из них всех Сидоровых и нужно ли вообще это делать для подсчёта их количества.

Рассмотрим ещё один пример. Допустим, мы хотим приготовить обед.

В императивной парадигме это выглядит как-то так:

  • купить мясо, огурцы, помидоры, соль;
  • порезать мясо, посолить;
  • поставить сковородку на плиту;

В декларативной: хочу на обед жареное мясо с овощами (неплохо звучит, правда? :)).

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

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

Павел Романченко, технический директор центра инновационных технологий и решений «Инфосистемы Джет»

Императивные языки, такие, как Java, Python, JavaScript, C, C++ занимают доминирующее положение в индустрии ПО, соответственно императивное программирование — самое распространённое. Смысл его в том, что императивная программа содержит прямые указания, что должен сделать компьютер и в каком порядке должны выполняться инструкции. Этот подход легко понять программисту, а компилятору — легко породить достаточно эффективный код.

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

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

Вообще в декларативных языках обычно отсутствует изменение переменных или обычно спрятано за каким-либо специальным механизмом.

Самый популярный язык РСУБД SQL так же является декларативным. На нём описывается конечный результат, а способ его получения генерируется сервером СУБД исходя из множества факторов.

Декларативное программирование может являться более сложным в понимании, но позволяет писать более безопасный и поддерживаемый код, который легко параллелится. А компиляторы декларативных языков имеют больше возможностей при оптимизации программ.

Что из себя представляют императивное и декларативное программирование?

Если кратко, то императивная программа содержит прямые указания, что должен сделать компьютер и в каком порядке должны выполняться инструкции. Примерами императивных языков являются Java, Python, JavaScript, C, C++.

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

Читайте также: