- Императивное программирование
- Декларативное программирование
- Серебряная пуля
- Путаница в терминологии
Практически любой код на любом языке можно писать по-разному. Можно по-разному дробить код на функции, по-разному называть переменные или менять глубину вложенности условных конструкций. Все это — метрики качества кода и отдельные составляющие, из которых складывается стиль написания кода.
Однако стиль кодирования практически не влияет на решение конкретной задачи и на архитектуру решения. Эти свойства определяются выбранной парадигмой программирования.
Парадигма программирования — это совокупность наших представлений о том, как решать ту или иную задачу. Мы начинаем применять парадигму еще до того, как начнем писать код. Сам код на конкретном языке всего лишь позволяет с той или иной степенью удобства записать наши мысли в виде программы.
Опытный программист умеет:
- Думать в нужном ключе и разных парадигмах
- Применять различные парадигмы
- Правильно выбирать парадигму под конкретную задачу
- Записывать свои мысли в коде на разных языках программирования
Можно сказать, что парадигма подходит для какого-либо языка программирования, когда для решения задачи не требуется бороться с языком и менять подходы. Если парадигма подходит языку, то программист просто записывает собственные мысли «как есть».
Python и большинство современных высокоуровневых языков программирования считаются мультипарадигменными. Другими словами, они позволяют использовать несколько парадигм с одинаковым уровнем удобства.
Язык C и другие низкоуровневые языки не могут себе позволить такую свободу, потому что код на таких языках должен быть эффективным. В таких языках решения максимально завязаны на то, как задачу понимает компьютер, а не разработчик.
Императивное программирование
Представим, что нам нужно решить какую-то сложную задачу. Ее нельзя решить в одно действие компьютера, поэтому мы описываем последовательность шагов, которые надо выполнить.
Широкие шаги разбиваются на более мелкие до тех пор, пока каждый отдельный шаг не станет понятен интерпретатору или компилятору выбранного языка. Проще говоря, мы продумываем и описываем то, как достичь нужного результата. Такое описание четкой последовательности шагов называется императивным программированием.
Императивное программирование сопряжено с изменением состояния компьютера. Большие программы постоянно модифицируют глобальные и локальные переменные: записывают что-то на диск, посылают или принимают из сети, запускают отдельные подпрограммы и процедуры.
Такой код дает максимально возможную эффективность. Но есть и минусы: он заставляет программиста держать в уме все, что меняется при выполнении каждого конкретного шага.
Большинство языков низкого уровня предполагает кодирование только в этой парадигме — ведь компьютер только и делает, что последовательно выполняет команды на машинном языке и меняет состояние памяти. Многие языки высокого уровня тоже в основном предполагают решение задач императивно.
Декларативное программирование
В работе над задачами мы сначала представляем себе нужный результат, а уже потом придумываем способ этого результата достичь. Этот подход используется и в программировании. Иногда программисту достаточно описать результат, а способы его достичь компьютер придумывает сам. Декларативное программирование — это и есть описание конечного результата.
Решая задачу в декларативном стиле, мы описываем, как результат соотносится со входными данными. При необходимости мы уточняем детали, пока интерпретатор не получит достаточно информации, чтобы дальше действовать самостоятельно. Уточняя наши требования, мы все еще не говорим компьютеру, как именно делать работу — мы лишь точнее описываем соотношение «входов» и «выходов».
Декларативное программирование часто похоже на написание некоторой формулы или соединение отдельных операций в конвейер, который из входных данных формирует выходные. Сложные формулы мы разбиваем на более простые, сложные операции делим на цепочки операций попроще. Во время декомпозиции не приходится думать, как будет меняться состояние компьютера, как он будет хранить промежуточные данные.
Это упрощает написание и чтение кода, но усложняет сам интерпретатор или компилятор. И тем сложнее делать интерпретаторы и компиляторы, которые позволят компьютеру работать эффективно. Поэтому языки низкого уровня практически не имеют средств для декларативного программирования, ведь для таких языков главное — это эффективность. При этом далеко не каждый язык высокого уровня предоставляет средства для решения любых задач строго декларативно. Обычно речь идет лишь об элементах декларативного программирования.
Серебряная пуля
Человеку свойственно думать в декларативном ключе. Возьмем для примера математику: мы знаем аксиомы и теоремы — например, «длина гипотенузы — это корень квадратный из суммы квадратов катетов». Обычно мы рассуждаем в таких декларативных формулировках.
Императивно та же мысль звучала бы так: «Берем первый катет, умножаем на себя, запоминаем, складываем и запоминаем результат. Берем второй катет, умножаем на себя, запоминаем, добавляем к предыдущему результату и запоминаем. Извлекаем корень из предыдущего результата».
Если бы наши компьютеры были бесконечно производительными и бесконечно понятливыми, то любой код был бы декларативным.
Однако таких идеальных вычислителей у нас нет и в ближайшее время не будет. И далеко не каждую задачу можно описать декларативно. Никакого идеального решения нет — эту мысль высказал инженер ПО Фредерик Брукс в своей известной статье «Серебряной пули нет».
Без идеального решения нам приходится довольствоваться:
- Чисто декларативным решением задач в ограниченных предметных областях — например, при работе с языком SQL и предметно-ориентированными языками
- Декларативным стилем с элементами императивного
На Python можно реализовывать декларативные предметно-ориентированные языки «под задачу». Но и это еще не все — можно писать декларативно с элементами императивности. Именно об этой второй возможности и рассказывает этот курс.
Путаница в терминологии
В источниках вы обязательно встретите словосочетания вроде «функциональный стиль». В таких случаях имеется в виду именно парадигма программирования, а не стиль написания кода. Поэтому ориентируйтесь на прилагательное «функциональный», а не на существительное «стиль».
Так же встречается вариация «в функциональном ключе» и другие ей подобные. Здесь тоже нужно обращать внимание на прилагательное.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.