Данная несколько выпадает из множества других статей. Её скорее следовало бы отнести к разделу Философия программирования.
Отражение парадигм программирования в языка
Статья представляет собой краткое изложение моей лекции.
На самом деле многие считают, что вопрос о парадигмах программирования - вопрос праздный. Отчасти и я так думаю. Но, однако, порассуждать о программировании совсем даже и не вредно. А что-же такое парадигма? Если просто, то это набор некоторых положений. Это справедливо для любой области. Если мы следуем этим положениям в программировании, то можно говорить, что мы программируем в конкретной парадигме. Но это мы возвращаемся к старому вопросу о том, что правильно, а что не правильно в программировании. Я уже много раз писал, что не знаю, что правильно, а что нет. Всё зависит от того, какие требования к вам предъявляют, и собираетесь ли вы их выполнять. Ну об этом я ещё напишу, а сейчас возвращаюсь к парадигмам.
Замечание
Почеркну, что речь в статье пойдёт не столько о концепции, как таковой, сколько о её поддержке в языках программировнаия. Язык ассемблера не способствует процедурному подходу, но его использовать в программах на языке ассемблера можно. Также последовательность изложенных парадигм не предполагает, что именно в такой последовательности они появлялись в программировании.
Доисторическая парадигма
Парадигмы программирования это продукт истории развития программирования. Надо сказать, что любая парадигма не умирает, а, либо живёт в последующих парадигмах, как их часть, либо используется в чистом виде, по тем или иным причинам (см. ниже).
А история программирования, чтобы там ни говорили, началась в 1940-х годах с появления первых элетронно-вычилитиельных машин.
Я бы выделили в начале доисторическую парадигму программирования, когда писали на машинном языке, т.е. записывали коды команд и данные непосредственно в ячейки памяти. На этом я даже и останавливаться не буду, хотя приходилось когда-то давным давно использовать и эту парадигму.
А первая историческая парадигма, которую мы назовём примитивной, появилась с появлением языка ассемблер.
На ассмеблере (см. Рисунок 1) для изменения хода выполнения прогаммы есть условные (jхх) и безусловные переходы (jmp). Есть конечно команды call (переход с сохранениям адреса возврата в стеке) и ret переход по адресу, который лежит в стеке. Но, конечно, это не функции, а просто специфические команды перехода. Примитивная парадигма перешла в другие языки, например, Pascal или C и продолжает жить до сих, как возможность того или иного языка (см. Рисунок 2)
На рисунке 2 пример примитивной парадигмы на языке Pascal. Заметьте, что что можно написать программу любой сложности используя только вот такую примитивную парадигма. Да читать и модернизировать её будет очень сложно, но это другой вопрос.
Структурное программирование
Следующая парадигма, которая появилась в 60-е годы это структурное программирование. Суть структурного программирования заключается в следующем: программа разбивается на блоки. Блок можно рассматривать как составной оператор. Требование структурного программирования заключается в том, у такого блока есть только один вход и один выход (см. Рисунок 3).
Конечно, наличие в Паскале или Си оператора goto портит всю картину. Принципы структурного программирования можно легко нарушить. Однако не нужно думать, что в языках, где нет такого оператора, всё обстоит так уж гладко. Возьмите хоть Python. Если условная конструкция с блоками стоит внутри цикла, то операторы break и continue легко нарушают вышеописанные принципы.
Процедурное программирование
Следующую парадигму обычно называют процедурным программированием. В языках программирования появляется элемент (процедура, функция) куда можно поместить код, который может вызываться многократно. Это уже даёт возможность сократить объём кода. Процедурный подход также позволяет использовать параметры, с помощью которых можно влиять на алгоритм обработки и полученный результат.
Ниже (рисунок 4) представлена простая программа с функцией.
Кстати в процедурном программировании сохраняется принцип структурного программирования: один вход и один выход. Однако сам инструментарий обычных языков программирования таков, что нарушить этот принцип достаточно легко: выйти из процедуры просто в любом месте кода, используя exit, return или ещё какой-либо оператор.
Модульное программирование
Конечно, во всех парадигмах ставилась задача улучшить технологию программирования, т.е. сократить время разработки и вероятность появления ошибок. Кроме того, в силу увеличения объёма кода, облегчить процесс коллективной разработки. Такой парадигмой является принцип модульного программироания. Большую программу можно разбить на несколько модулей, в которых будут содержаться процедуры и функции программы. При трансляции программы или её выполнении все модули собираются в единую исполняемую программу.
Продемонстрируем двухмодульную программу на языке программирования С (см. Рисунок 5 и 6).
Проограмма на рисунках 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)
Лишний раз подчеркну, что соотношение между последующими и предыдущими парадигмами не всегда является простым. Скажем парадигма ООП не противоречит модульному программированию. При этом в парадигме ООП нет требований использовать модульное программирование. А вот требования структурного программирования отрицают предыдущую парадигму с её условными и безусловными переходами. При этом в обычных алгоритмических языках нет строгого соблюдения одной парадигмы. Мне это всё нравится, есть поле для творчества и личных предпочтений.
Функциональное программирование
Принцип функционального программирования заключается в том, чтобы не использовать переменные: есть только функции и их параметры. При этом сами функции и являются параметрами. Кстати многие языки программирования вполне себе можно использовать в такой парадигме. Взять хотя бы Python (см. Рисунок 8).
В программе, решающей линейное уравнение вида ax+b=c, есть только функции. Стандартные input(), print(), float() и определяемая в программе solve(). При этом сами функции также являются параметрами.
Рекурсивное программирование
Рекурсивному программированию на моём канале посвящена целая подоборка статей
Ниже, рисунок 9 представлен пример реализации цикла рекурсивным способом
Декларативное программирование
Последняя парадигма, на которой хотелось бы остановиться, это декларативный подход.
Декларативный подход лучше всего демонстрируется языком SQL. См. мою подюорку
В чистом виде, его нельзя назвать алгоритмическим, хотя часто его расширяют, чтобы писать полноценные программы. Суть декларативного языка заключается в том, что мы не прописываем алгоритм, который должен привести к результату. Мы указывам (декларируем), что мы хотим получить или сделать.
Замечание
Поскольку мне тут уже в комментариях написали, то я подчеркну, что речь в статье идёт о структуре программы, а не о способе проектирования. Способы проектирования это совсем другая история.
Пишите свои предложения и замечания и занимайтесь программированием, хотя бы для поддержания уровня интеллекта.