- Две основные ветви парадигм
- Основные парадигмы программирования
- Процедурное программирование (Procedural)
- Объектно-ориентированное программирование (Object-Oriented)
- Функциональное программирование (Functional)
- Декларативное программирование (Declarative)
- Логическое программирование (Logic)
- Реактивное программирование (Reactive)
- Другие парадигмы
- Сравнение основных парадигм
- История развития парадигм
- Мультипарадигменность
- Критика парадигм
Парадигма программирования — это совокупность правил, принципов и методик, используемых при разработке программного обеспечения. Это высокоуровневый способ концептуализации и структуризации реализации компьютерной программы. Парадигма программирования определяет стиль написания программы, способ организации кода и подход к решению задач.
Языки программирования не привязаны к конкретной парадигме — один язык может поддерживать одну или несколько парадигм одновременно. Это называется мультипарадигменностью.
Две основные ветви парадигм
Все парадигмы программирования условно разделяются на две основные категории:
Императивные парадигмы (Imperative)
Императивные парадигмы основаны на том, что код прямо контролирует порядок выполнения и изменение состояния программы. Программист дает явные инструкции, как выполнить задачу.
- Четко определенный порядок операций
- Явное изменение состояния программы
- Побочные эффекты (side effects) разрешены
- Коммуникация между частями кода часто неявная
Декларативные парадигмы (Declarative)
Декларативные парадигмы основаны на описании желаемого результата без указания деталей того, как его достичь. Программист описывает ЧТО нужно сделать, а не КАК.
- Описание свойств желаемого результата
- Порядок операций не определен явно
- Система сама выбирает порядок выполнения
- Более высокий уровень абстракции
Основные парадигмы программирования
Процедурное программирование (Procedural)
Процедурное программирование — это парадигма, которая организует программу как последовательность процедур (функций или подпрограмм), вызывающих друг друга.
- Разбиение монолитного кода на подпрограммы с определёнными инструкциями
- Замена конструкций
gotoна более структурированные конструкции (циклы, условия) - Улучшение модульности и поддерживаемости кода
- Соблюдение структурированного программирования
Пример в псевдокоде:
textfunction pourIngredients()
// Налить муку в миску
// Добавить яйца
// Добавить молоко
function mixAndBake()
// Смешать ингредиенты
// Залить тесто в форму
// Печь 35 минут
pourIngredients()
mixAndBake()
Языки: C, Pascal, COBOL, FORTRAN
Объектно-ориентированное программирование (Object-Oriented)
ООП — парадигма, при которой программа организована как набор объектов, содержащих как данные (свойства), так и поведение (методы). Каждый объект создается из класса, который служит шаблоном.
- Классы — шаблон для создания объектов
- Объекты — конкретные экземпляры класса
- Инкапсуляция — группировка данных и методов
- Наследование — переиспользование кода через иерархию классов
- Полиморфизм — способность объектов принимать разные формы
- Абстракция — скрытие внутренних деталей
- Разделение программы между специалистами упрощено
- Код проще поддерживать и тестировать
- Естественное отражение реальных объектов в коде
- Моделирование бизнес-проблем в коде
Языки: Java, C++, Python, C#, JavaScript, PHP
Функциональное программирование (Functional)
Функциональное программирование — парадигма, при которой программа структурируется как последовательность вычислений функций, а не как последовательность операций изменения состояния.
- Функции как первоклассные объекты — функции могут присваиваться переменным, передаваться как аргументы, возвращаться из других функций
- Чистые функции (Pure Functions) — функция зависит только от своих входных параметров и всегда дает одинаковый результат при одинаковых входных данных
- Отсутствие побочных эффектов — функция не изменяет внешнее состояние программы
- Неизменяемость данных (Immutability) — данные не изменяются, вместо этого создаются новые копии
- Рекурсия — часто используется вместо циклов
Пример в JavaScript:
javascriptconst nums = [1,4,3,6,7,8,9,2]
const result = nums.filter(num => num > 5)
console.log(result) // [6, 7, 8, 9] Здесь функция filter — чистая функция, которая не изменяет исходный массив, а возвращает новый.
- Код легче тестировать (нет неявных зависимостей)
- Проще избежать ошибок, связанных с состоянием
- Отличная поддержка параллельной обработки
- Лучшая модульность
Языки: Haskell, Lisp, Scheme, Erlang, F#, Clojure
Декларативное программирование (Declarative)
Декларативное программирование — парадигма, при которой программист описывает желаемый результат, а система сама выбирает способ его достижения.
Основная идея: отличие от императивного подхода в том, что вместо пошаговых инструкций мы описываем свойства результата.
Пример:
javascript// Декларативно: что нам нужно
const nums = [1,4,3,6,7,8,9,2]
console.log(nums.filter(num => num > 5)) // [6, 7, 8, 9]
// Императивно: как это делать
const nums = [1,4,3,6,7,8,9,2]
const result = []
for (let i = 0; i < nums.length; i++) {
if (nums[i] > 5) result.push(nums[i])
}
console.log(result) // [6, 7, 8, 9]
Подкатегории декларативного программирования:
- Функциональное программирование — результат определяется как значение серии вычислений функций
- Логическое программирование — результат определяется как ответ на вопрос о системе фактов и правил
- Реактивное программирование — результат определяется с потоками данных и распространением изменений
Языки и технологии: SQL, HTML, CSS, React, XSLT, Terraform
Логическое программирование (Logic)
Логическое программирование — парадигма, при которой вычисление рассматривается как автоматизированное логическое рассуждение над телом знания.
- Факты о предметной области выражаются как логические формулы
- Программа выполняется путём применения правил вывода
- Система автоматически ищет решение или доказывает несовместимость формул
Реактивное программирование (Reactive)
Реактивное программирование — парадигма, при которой программа реагирует на потоки данных и изменение состояния.
- Фокус на потоках данных (data streams)
- Распространение изменений через систему
- Асинхронная обработка событий
Технологии: RxJS, React Streams
Другие парадигмы
Конкурентное программирование (Concurrent Programming)
Программирование потока данных (Dataflow Programming)
- Парадигма, при которой пересчет формул происходит автоматически при изменении данных. Пример — электронные таблицы.
Программирование ограничений (Constraint Programming)
Метапрограммирование (Metaprogramming)
- Парадигма, при которой программа может писать или манипулировать другими программами, включая саму себя.
Визуальное программирование (Visual Programming)
Сравнение основных парадигм
| Парадигма | Основной подход | Фокус | Языки-примеры |
|---|---|---|---|
| Процедурная | Как это делать | Пошаговые инструкции | C, Pascal, COBOL |
| ООП | Как это делать | Объекты и их взаимодействие | Java, C++, Python |
| Функциональная | Что нужно | Функции и их композиция | Haskell, Lisp, Erlang |
| Декларативная | Что нужно | Описание результата | SQL, HTML, CSS |
| Логическая | Что нужно | Логическое рассуждение | Prolog, Mercury |
История развития парадигм
Концепция парадигмы программирования была введена в 1978 году в Turing Award лекции Роберта У. Флойда, где он ссылался на понятие парадигмы из работы Томаса Куна «Структура научных революций» (1962).
- 1960-е: Структурированное программирование
- 1970-е: Объектно-ориентированное программирование начало развиваться
- 1980-е: ООП стал основным подходом
- 1990-е: Функциональное программирование получило новый импульс
- 2000-е: Декларативное и реактивное программирование стали популярны
Мультипарадигменность
Большинство современных языков программирования поддерживают мультипарадигменность — они позволяют использовать элементы разных парадигм в одной программе:
- JavaScript — процедурное, ООП, функциональное, декларативное
- Python — процедурное, ООП, функциональное
- C++ — процедурное, ООП, функциональное
- Java — ООП, функциональное (в Java 8+)
Критика парадигм
Некоторые исследователи критикуют использование парадигм как классификационной системы, аргументируя тем, что большинство языков не могут быть строго отнесены к одной парадигме и содержат элементы нескольких. Это признание мультипарадигменности является более точным описанием современных языков программирования.
