Найти в Дзене

О парадигмах программирования

Оглавление

Данная несколько выпадает из множества других статей. Её скорее следовало бы отнести к разделу Философия программирования.

programmer's notes (python and more) | Дзен
Базовый курс программирования на Python | programmer's notes (python and more) | Дзен
Философия программирования | programmer's notes (python and more) | Дзен

Отражение парадигм программирования в языка

Статья представляет собой краткое изложение моей лекции.

На самом деле многие считают, что вопрос о парадигмах программирования - вопрос праздный. Отчасти и я так думаю. Но, однако, порассуждать о программировании совсем даже и не вредно. А что-же такое парадигма? Если просто, то это набор некоторых положений. Это справедливо для любой области. Если мы следуем этим положениям в программировании, то можно говорить, что мы программируем в конкретной парадигме. Но это мы возвращаемся к старому вопросу о том, что правильно, а что не правильно в программировании. Я уже много раз писал, что не знаю, что правильно, а что нет. Всё зависит от того, какие требования к вам предъявляют, и собираетесь ли вы их выполнять. Ну об этом я ещё напишу, а сейчас возвращаюсь к парадигмам.

Замечание
Почеркну, что речь в статье пойдёт не столько о концепции, как таковой, сколько о её поддержке в языках программировнаия. Язык ассемблера не способствует процедурному подходу, но его использовать в программах на языке ассемблера можно. Также последовательность изложенных парадигм не предполагает, что именно в такой последовательности они появлялись в программировании.

Доисторическая парадигма

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

А история программирования, чтобы там ни говорили, началась в 1940-х годах с появления первых элетронно-вычилитиельных машин.

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

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

Рисунок 1. Пример программы на ассемблере с переходами. Текст программы см. ниже по ссылке
Рисунок 1. Пример программы на ассемблере с переходами. Текст программы см. ниже по ссылке
primer341.s

На ассмеблере (см. Рисунок 1) для изменения хода выполнения прогаммы есть условные (jхх) и безусловные переходы (jmp). Есть конечно команды call (переход с сохранениям адреса возврата в стеке) и ret переход по адресу, который лежит в стеке. Но, конечно, это не функции, а просто специфические команды перехода. Примитивная парадигма перешла в другие языки, например, Pascal или C и продолжает жить до сих, как возможность того или иного языка (см. Рисунок 2)

Рисунок 2. Примитивная парадигма программирования на Паскале
Рисунок 2. Примитивная парадигма программирования на Паскале
primer342.pas

На рисунке 2 пример примитивной парадигмы на языке Pascal. Заметьте, что что можно написать программу любой сложности используя только вот такую примитивную парадигма. Да читать и модернизировать её будет очень сложно, но это другой вопрос.

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

Следующая парадигма, которая появилась в 60-е годы это структурное программирование. Суть структурного программирования заключается в следующем: программа разбивается на блоки. Блок можно рассматривать как составной оператор. Требование структурного программирования заключается в том, у такого блока есть только один вход и один выход (см. Рисунок 3).

Рисунок 3. Пример структурного программирования. Текст программы см. ниже по ссылке
Рисунок 3. Пример структурного программирования. Текст программы см. ниже по ссылке
primer343.pas

Конечно, наличие в Паскале или Си оператора goto портит всю картину. Принципы структурного программирования можно легко нарушить. Однако не нужно думать, что в языках, где нет такого оператора, всё обстоит так уж гладко. Возьмите хоть Python. Если условная конструкция с блоками стоит внутри цикла, то операторы break и continue легко нарушают вышеописанные принципы.

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

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

Ниже (рисунок 4) представлена простая программа с функцией.

Рисунок 4. Пример программы на языке Pascal с функцией. Текст программы см. ниже по ссылке
Рисунок 4. Пример программы на языке Pascal с функцией. Текст программы см. ниже по ссылке
primer344.pas

Кстати в процедурном программировании сохраняется принцип структурного программирования: один вход и один выход. Однако сам инструментарий обычных языков программирования таков, что нарушить этот принцип достаточно легко: выйти из процедуры просто в любом месте кода, используя exit, return или ещё какой-либо оператор.

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

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

Продемонстрируем двухмодульную программу на языке программирования С (см. Рисунок 5 и 6).

Рисунок 5. Главный модуль программы. Текст программы см. ниже по ссылке
Рисунок 5. Главный модуль программы. Текст программы см. ниже по ссылке
main.c

Рисунок 6. Модуль программы (см. Рисунок 5). Текст программы см. по ссылке ниже
Рисунок 6. Модуль программы (см. Рисунок 5). Текст программы см. по ссылке ниже
main1.c

Проограмма на рисунках 5 и 6 состоит из модулей main.c и main1.c. Трансляция программы осущес твляется последовательностью команд

gcc -c main.c
gcc -c main1.c
gcc -o main main.o main1.o

Процесс трансляции, как мы видим, состоит из двух стадий: 1. Компилирование текстов модулей в объектный код. 2. Сборка объектных модулей со стандартной библиотекой языка C и создание исполняемого модуля.

О многомодульном программирование на языке Python можно прочесть в мой статье здесь на канале:

Объектно-ориентированное программирование

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

Приведем простой пример программы с использованием ООП (рисунок 7)

Рисунок 7. Пример программы на языке Python с использованием РРП. Текст программы см. ниже по ссылке
Рисунок 7. Пример программы на языке Python с использованием РРП. Текст программы см. ниже по ссылке
primer345.py

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

Функциональное программирование

Принцип функционального программирования заключается в том, чтобы не использовать переменные: есть только функции и их параметры. При этом сами функции и являются параметрами. Кстати многие языки программирования вполне себе можно использовать в такой парадигме. Взять хотя бы Python (см. Рисунок 8).

Рисунок 8. Пример программы, написанной в функциональном стиле. Текст программы см. ниже по ссылке
Рисунок 8. Пример программы, написанной в функциональном стиле. Текст программы см. ниже по ссылке
primer346.py

В программе, решающей линейное уравнение вида ax+b=c, есть только функции. Стандартные input(), print(), float() и определяемая в программе solve(). При этом сами функции также являются параметрами.

Рекурсивное программирование

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

Ниже, рисунок 9 представлен пример реализации цикла рекурсивным способом

Рисунок 9. Пример реализации цикла в рекурсивной парадигме. Текст программы см. ниже по ссылке
Рисунок 9. Пример реализации цикла в рекурсивной парадигме. Текст программы см. ниже по ссылке
primer347.py

Декларативное программирование

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

Декларативный подход лучше всего демонстрируется языком SQL. См. мою подюорку

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

Рисунок 10. Запрос на языке SQL, пример элемента декларативного подхода. Ссылка на запрос см. ниже
Рисунок 10. Запрос на языке SQL, пример элемента декларативного подхода. Ссылка на запрос см. ниже
1.sql

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

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

В какой парадигме вы любите программировать в утренние часы?
В какой парадигме вы любите программировать в утренние часы?