...

воскресенье, 18 мая 2014 г.

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


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


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



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






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

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


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




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

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


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


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


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




— Инструкция

— Состояние

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




— Присваивание

— Переход

— Память

— Указатель

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




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



— Языки ассемблера

— Fortran

— Algol

— Cobol

— Pascal

— C

— C++

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



— Python

— Ruby

— Java

— C#

— PHP

— Haskell (через монады)

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


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






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

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


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


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




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

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


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


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


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




— Блок

— Цикл

— Ветвление

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




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



— C

— Pascal

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



— 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 — тоже модуль, хоть и некоторые языки разделяют понятие модуля и пакета (в таких языках пакет — набор модулей и/или набор других пакетов).


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


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




— Модуль

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

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




— Пакет

— Инкапсуляция

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




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



— Haskell

— Pascal

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



— Java

— C#

— ActionScript 3

Поддерживают частично:

— C/C++


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


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




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

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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий