Принципы процедурных языков программирования

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

Базовыми действиями в императивном программировании остаются присваивание и вызов подпрограммы. В свое время использование подпрограмм стало одной из основополагающих идей и даже получило самостоятельное название — программирование с использованием процедур, или процедурное программирование . Процедурное программирование дает возможность повторного использования кода и в некотором смысле реализует принцип матрешки. Процедура — блок, который раскрывается в другом месте, а из данной программы лишь вызывается (указанием ее имени). ЗАМЕЧАНИЕ Процедурное программирование — лишь одна из вариаций древнейшего принципа решения сложных задач «разделяй и властвуй!». Принцип заключается в разбиении сложной задачи на менее сложные подзадачи, каждая из которых либо также разбивается на еще более простые, либо решается доступными средствами.

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

49 исходными текстами, классы, пакеты, процедуры, модули, функции, пространства имен и т. д. (это зависит от языка, в некоторых из них возможны несколько вариантов разбиения). Пока будем использовать для всех них единый термин — модуль (в обобщенном смысле). В программировании используются несколько принципов разделения программы на модули. Один из них требует, чтобы размер каждой отдельной процедуры (функции, класса) был обозримым, не превышая, скажем, двух стандартных страниц. Другие обоснованные соображения деления программы на модули основываются на функциональной законченности, или разбиении программы на части в соответствии с выполняемыми самостоятельными функциями. При этом руководствуются принципами сильной связи внутри модуля и слабой связи между модулями (которая тем не менее должна быть достаточной для решения программой поставленных перед нею задач). Слабая взаимозависимость модулей позволяет более удобно заменять версию данного модуля в случае необходимости (нахождение и исправление ошибки или доработка программы) и распределеять задачи программирования в коллективах — а современные программы часто создаются десятками, а то и сотнями разработчиков. ЗАМЕЧАНИЕ Поскольку вызов процедуры требует некоторых затрат времени процессора и памяти, иногда целесообразна замена некоторых процедур малого размера так называемыми встроенными (inline) функциями. Фактически, процедура превращается в дублирующиеся в нескольких местах блоки команд, что позволяет повысить скорость исполнения программы. Иногда в языках программирования используются так называемые замыкания — фактически, вспомогательные функции, определяемые и используемые внутри родительской функции и использующие ее локальные переменные, а не только свои переменные-параметры. В программе замыкание выглядит как функция, находящаяся целиком в теле другой функции. При этом вложенная функция содержит ссылки на переменные внешней. Каждый раз при выполнении родительской функции происходит создание нового экземпляра внутренней функции с новыми ссылками на переменные внешней функции. При этом ссылки на переменные внешней функции действительны до тех пор, пока работает вложенная функция, даже если внешняя функция закончила работу. Пример на языке PHP: function outer($x) //Определение внешней функции < $y=2; //Локальная переменная внешней функции

Читайте также:  Программирование пульт hormann hse2 868 bs

50 $inner=function ($a) use ($x, $y) //Определение внутренней функции < $b=4; //Локальная переменная внутренней функции /* А дальше складываются переменные внутренней и * внешней функций, как будто все они локальные * переменные внутренней функции */ $res=$x+$y+$a+$b; echo $res; //Результат 10 в нашем примере. >; $inner(3); //Вызов внутренней функции > outer(1); Механизм замыканий тесно связан с лямбда-функциями (безымянными функциями, использующими текущий контекст программы). Первоначально они нашли широкое применение в функциональном программировании (языки Лисп — см. соответствующий раздел настоящей книги, Хаскелл, Scheme), но затем получили распространение и в языках императивной парадигмы (Ruby, PHP, Питон и др.). Пример на языке Питон: (lambda x: x*2)(3) → 6

Контрольные вопросы и упражнения

3. Как выглядит императивная программа? 4. В чем назначение номеров строк в программе? В чем назначение меток? 5. Что такое процедурная и декларативная секции программы? 6. Что такое линейная программа? Приведите примеры. 7. В чем состоят функции и какова структура оператора присваивания? 8. В чем заключается назначение и какова структура условного оператора? 9. В чем заключается назначение, каковы варианты и структура оператора выбора? 10.Каким образом можно организовать повторение одних и тех же действий в программе? 11.Что такое рекурсия? В чем назначение граничного условия в рекурсивных программах? 12.Что такое итерация? В чем преимущества и недостатки итерации по сравнению с рекурсией?

Источник

«Забытые» парадигмы программирования

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

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

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

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

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

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

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

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

Читайте также:  Лоджикар 4 программирование брелка

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

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

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

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

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

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

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

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

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

— Python
— Ruby
— Java
— C#
— PHP
— Haskell (через монады)

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

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

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

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

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

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

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

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

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

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

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

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

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

— C#
— Java
— Python
— Ruby
— JavaScript

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

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

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

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

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

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

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

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

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

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

Читайте также:  Двойственность линейного программирования кратко

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

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

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

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

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

— C
— C++
— Pascal
— Object Pascal

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

— C#
— Java
— Ruby
— Python
— JavaScript

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Источник

Оцените статью