Макияж. Уход за волосами. Уход за кожей

Макияж. Уход за волосами. Уход за кожей

» » Секция «Проблемы преподавания информатики. Парадигмы программирования Основы парадигмы структурного программирования

Секция «Проблемы преподавания информатики. Парадигмы программирования Основы парадигмы структурного программирования

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

Прикладное программирование подчинено проблемной направленности, отражающей компьютеризацию информационных и вычислительных процессов численной обработки, исследованных задолго до появления ЭВМ. Именно здесь быстро проявился явный практический результат. Естественно, в таких областях программирование мало чем отличается от кодирования, для него, как правило, достаточно операторного стиля представления действий. В практике прикладного программирования принято доверять проверенным шаблонам и библиотекам процедур, избегать рискованных экспериментов. Ценится точность и устойчивость научных расчетов. Язык Фортран -- ветеран прикладного программирования, постепенно стал несколько уступать в этой области Паскалю, Си, а на суперкомпьютерах -- языкам параллельного программирования, таким как Sisal.

Теоретическое программирование придерживается публикационной направленности, нацеленной на сопоставимость результатов научных экспериментов в области программирования и информатики. Программирование пытается выразить свои формальные модели, показать их значимость и фундаментальность. Эти модели унаследовали основные черты родственных математических понятий и утвердились как алгоритмический подход в информатике. Стремление к доказательности построений и оценка их эффективности, правдоподобия, правильности, корректности и других формализуемых отношений на схемах и текстах программ послужили основой структурированного программирования и других методик достижения надежности процесса разработки программ, например грамотное программирование. Стандартные подмножества Алгола и Паскаля, послужившие рабочим материалом для теории программирования, сменились более удобными для экспериментирования аппликативными языками, такими как ML, Miranda, Scheme, Haskell и другие. Теперь к ним присоединяются нововведения в C и Java.

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

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

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

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

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

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

Трансформационное программирование методологически объединило технику оптимизации программ, макрогенерации и частичных вычислений. Центральное понятие в этой области -- эквивалентность информации. Она проявляется в определении преобразований программ и процессов, в поиске критериев применимости преобразований, в выборе стратегии их использования. Смешанные вычисления, отложенные действия, "ленивое" программирование, задержанные процессы и т.п. используются как методы повышения эффективности информационной обработки при некоторых дополнительно выявляемых условиях.

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

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

Когнитивный подход с интероперабельным стилем визуально-интерфейсной разработки открытых систем и использование новых аудио-видео средств и нестандартных устройств открывают пути активизации восприятия сложной информации и упрощения ее адекватной обработки.

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

РЕКУРСИВНЫЕ ВЫЧИСЛЕНИЯ В РАЗЛИЧНЫХ ПАРАДИГМАХ ПРОГРАММИРОВАНИЯ.

Г.В. Ваныкина, А.В. Якушин

Тульский Государственный педагогический университет им. Л. Н. Толстого

[email protected]

1. Парадигмы современного программирования.

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

Необходимо отметить, что слово «парадигма» пришло в программирование из оказавшей большое влияние книги «Структура научных революций», написанной историком науки Томасом Куном в 1970 году. Кун использовал этот термин, чтобы описывать набор теорий, стандартов и методов, которые совместно представляют собой способ организации научного знания ‑ иными словами, способ видения мира. Основное положение Куна состоит в том, что революции в науке происходят, когда старая парадигма пересматривается, отвергается и заменяется новой.

В сходном смысле как модель или пример, и в целом как организующий подход это слово использовано в лекции «Парадигмы программирования» Роберта Флойда, лауреата премии Тьюринга 1979 года.

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

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

В зависимости от способа декомпозиции можно выделить следующие основные парадигмы программирования, представленные в таблице 1.

Таблица 1. Основные парадигмы программирования

Название парадигмы

Способ декомпозиции

Пример языков программирования

Императивная

(синонимы: директивная, процедурная)

Подпрограммы, абстрактные типы данных

Fortran, C, Pascal , Basic

Декларативная

(составные части: логическая и функциональная)

Цели, выраженные в терминах исчисления предикатов. Правила "если - то"

Lisp, Scheme, Prolog, ML, Haskell

Объектно-ориентированная

Классы и объекты

Java, C++, Ruby

Программирование в ограничениях

Инвариантные отношения , система ограничений

языки CLP(X), SETL, Prolog III

Сценарная

Элементарный сценарий обработки или управления

Perl , PHP, Pyton , ASP

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

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

Проблема становления алгоритмической культуры школьников как основополагающего компонента информационной культуры решается с точки зрения различных парадигм программирования в зависимости от ряда факторов: учебной программы для преподавания курса информатики, технического и программного обеспечения, а также личностных и профессиональных качеств преподавателя. Раздел «Программирование» в рамках общеобразовательного уровня подготовки школьников предполагает изучение основ императивной (Basic , Pascal , C , школьный алгоритмический язык) либо объектно-ориентированной (Delphi , C ++, Java ) парадигм. Профильная подготовка старшеклассников по естественно научному направлению реализуется, как правило, также в рамках вышеперечисленных парадигм. Следует, однако, отметить, что обучение программированию на конкретном языке не является основной задачей в реализации алгоритмической подготовки школьников. Гораздо более приоритетным направлением выступает обучение алгоритмическому подходу в решении задач, умению оценивать эффективность разработанного алгоритма с точки зрения решаемой задачи, выбору технологии для его реализации – то есть, речь идет о знакомстве с методами разработки алгоритмических моделей, реализация которых возможна в рамках любой парадигмы.

Развитие различных парадигм программирования проходило параллельно друг другу. Долгое время императивный подход был главенствующим, в 70-е, 80-е годы акцент сместился в сторону исследования неклассических парадигм, 90-е годы ознаменованы бурным развитием объектно-ориентированной парадигмы и внедрения ее элементов в другие. Развитие языков программирования с точки зрения различных парадигм представлено на рис.1

Fortran

Algol,C

Pascal

Modula

Oberon

Директивная

Basic

LISP

ML, Scheme

Haskell

Декларативная

Prolog

CProlog

VB, C++, Object Pascal

Java, C#

Объектно-ориентированная

Smalltalk

Ruby

SETL

Программирование в ограничениях

Prolog III

СPL (Х)

Perl

Pyton

Сценарная

PHP, ASP

Рис1. Развитие языков и парадигм программирования

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

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

2. Императивная парадигма.

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

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

Логическое программирование, основано на логике предикатов. Логика предикатов – это ветвь формальной логики, получившая развитие в XX веке. В логическом программировании основное внимание уделяется описанию структуры прикладной задачи, а не выработке предписаний компьютеру, что ему следует делать. В логическом программировании программа представляет собой некоторую теорию (описанную на достаточно ограниченном языке) и утверждение, которое нужно доказать. В доказательстве этого утверждения и будет заключаться исполнение программы.

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

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

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

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

Все объекты являются представителями, или экземплярами , классов. Метод, активизируемый объектом в ответ на сообщение, определяется классом, к которому принадлежит получатель сообщения. Все объекты одного класса используют одни и те же методы в ответ на одинаковые сообщения. Классы представляются в виде иерархической древовидной структуры, в которой классы с более общими чертами располагаются в корне дерева, а специализированные классы и, в конечном итоге, индивидуумы располагаются в ветвях. Уже в самой объектной декомпозиции содержатся элементы рекурсивных построений, поскольку полученная таким образом иерархия объектов обладает элементами самоподобия. Как известно, в основе объектно-ориентированного программирования лежат три основных понятия: инкапсуляция (сокрытие данных в классе или методе); наследование; полиморфизм. Инкапсуляцию можно представить, как защитную оболочку вокруг кода данных, с которыми этот код работает. Оболочка задает поведение и защищает код от произвольного доступа извне. Наследование – это процесс, в результате которого один тип наследует свойства другого типа. Полиморфизм – это концепция, позволяющая иметь различные реализации для одного и того же метода, которые будут выбираться в зависимости от типа объекта, переданного методу при вызове.

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

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

5. Программирование в ограничениях.

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

Программирование в ограничениях тесно связано с традиционным логическим программированием. Большинство систем программирования в ограничениях представляют собой интерпретатор языка Prolog со встроенным механизмом для решения определенного класса задач удовлетворения ограничениям. Программирование в таких системах называют логическим программированием в ограничениях (Constraint Logic Programming или CLP), а большинство языков или библиотек называются CLP(X), где X указывает на класс решаемых задач.

Например, CLP(B) означает возможность решать уравнения с булевыми переменными. CLP(Q) – уравнения в рациональных числах, а CLP(R) – в вещественных. Наиболее популярны решатели задач на конечных множествах целых чисел CLP(FD).

Постановка задачи – это конечный набор переменных X = { x 1 , ..., x n }, соответствующих им конечных (перечислимых) множеств значений D X = { dx 1 , ..., dx n }, и набор ограничений C = { c 1 ,..., c m }. Система ограничений может включать в себя уравнения, неравенства, логические функции, а также любые допустимые формальные конструкции, связывающие переменные из набора X . Решение задачи состоит в построении набора переменных, удовлетворяющего всем ограничениям c i ,где i = 1,.., m .

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

6. Сценарная парадигма.

Сценарные языки . Сценарные языки, или языки скриптов (scripting languages), за последние годы сделали огромный шаг вперед. Еще лет десять назад им отводилась роль вспомогательных средств, сейчас же скепсис по отношению к ним сменился интересом и признанием.

Сценарные языки имеют достаточно длительную историю развития. Концепция сценарного программирования явилась как естественное развитие языка LISP . К первым сценарным языкам относят встроенные средства управления командной оболочки операционной системой. Командный файл на языке операционной системы, представляет собой управляющий сценарий, который выполняет заданную последовательность действий. Можно сказать, что сценарий «склеивает» различные части операционной системы и осуществляет их взаимодействие.

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

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

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

Сценарные языки для web -разработки в основном созданы в 90-е годы XX века и включают в себя элементы различных парадигм программирования от императивной до объектно-ориентированной. Среди наиболее мощных и популярных скриптовых систем можно отметить следующие: Perl , Pyton , PHP , ASP . Синтаксис и семантика различных сценарных языков весьма похожи. Это обусловлено значительным влиянием языков С и С++ на сообщество программистов. Поддержка рекурсии в сценарных языках реализована аналогично императивной и объектно-ориентированной парадигмам.

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

(ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ)
  • Парадигмы и технологии программирования
    Задачи главы 1. Изучить понятия «парадигма программирования», «технология программирования». 2. Получить общее представление о современных технологиях создания программного обеспечения. 3. Изучить этапы создания структурной программы. 4. Познакомиться с моделями жизненного цикла разработки программного...
  • Парадигмы программирования SE
    SWEBOK включает ряд парадигм программирования См.: Лаврищева Е. М. Парадигмы программирования сборочного типа в программнойинженерии // УКРПрог-2014. № 2-3. С. 121-133. . В его учебные курсы по программированию включены следующие: процедурное программирование (курс CS1011 «Programming fundamentals»),...
    (ПРОГРАММНАЯ ИНЖЕНЕРИЯ И ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ СЛОЖНЫХ СИСТЕМ)
  • ПАРАДИГМЫ ПРОГРАММИРОВАНИЯ
    МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ. БАЗОВЫЕ ПОНЯТИЯ Одна из ключевых проблем современного программирования - повторное использование модулей и компонентов (КПИ). Ими могли быть программы, подпрограммы, алгоритмы, спецификации и т. п., пригодные для использования при разработке новых более сложных ПС....
    (ПРОГРАММНАЯ ИНЖЕНЕРИЯ. ПАРАДИГМЫ, ТЕХНОЛОГИИ И CASE-СРЕДСТВА)
  • Процедурная парадигма
    Процедурная парадигма была хронологически первой и долгое время превалировала. В настоящее время она постепенно уступает свое место объектно-ориентированной парадигме, хотя все еще занимает порядка половины рынка разработки программного обеспечения. Она применяется на всех уровнях разработки программного...
    (АЛГОРИТМИЗАЦИЯ И ПРОГРАММИРОВАНИЕ)
  • Декларативная и процедурная память
    Еще одним самостоятельным, независимым от других способом функциональной организации памяти является ее разделение на декларативную и процедурную. Эти два способа организации памяти имеют вполне понятную функциональную основу. Форма декларативной памяти предназначена для поддержки мыслительных...
    (Психология и педагогика)
  • И казалось, что необходимость проектирования и программирования именно в стиле ООП никем не оспариваются. Но все же со временем я столкнулся с непониманием. Это будет чисто историческая теоретическая статья. Конечно, даже без попытки обхвата всей широты темы. Но это так сказать посыл молодому разработчику, который читает по верхам и не может выбрать каких принципов и правил ему придерживаться, что первично, а что вторично.

    Заглавие этой темы для многих сейчас может показать очень спорным (и скорее намерено провокационным, но для дела:)). Но все же мы постараемся это здесь обосновать и понять какими свойствами должна обладать парадигма программирования, чтобы иметь право называться парадигмой.

    Единственно прошу, если прочитали по диагонали - комментируйте сдержано.

    Что нам говорит Флойд о парадигмах?

    Термин «парадигма программирования» ввел Роберт Флойд (""R. W. Floyd."" ""Communications of the ACM"", 22(8):455-460, 1979. Русский перевод см. в кн.: Лекции лауреатов премии Тьюринга за первые двадцать лет (1966-1985), М.: МИР, 1993.). Он в своей лекции в 1979 году говорит о следующем:

    Знакомый пример парадигмы программирования - это структурное программирование, которая, кажется, доминирующей парадигмой в методологии программирования. Она разделяется на две фазы. В первой фазе, нисходящего проектирования, проблема разделяется на небольшое количество более простых подпроблем. Это постепенное иерархическое разложение продолжается пока возникнет выделенные подпроблемы, которые достаточно просты, чтобы с ними справиться непосредственно. Вторая фаза парадигмы структурного программирования влечет за собой работу вверх от конкретных объектов и функций к более абстрактным объектам и функциям, используемые всюду в модулях, произведенных нисходящим проектированием. Но парадигма структурного программирования не универсальна. Даже её самые ярые защитники признали бы, что её отдельно недостаточно, чтобы сделать все сложные проблемы легкими. Другие парадигмы высокого уровня более специализированного типа продолжают быть важными. (Это не точный перевод, а авторская компиляция на основе лекции Р. Флойда, но максимально придерживаясь его слов. Формулировки изменены и скомпонованы лишь для выделения основной мысли Р.Флойда и понятного его изложения.)

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

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

    Особенности парадигм более высокого уровня

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

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

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

    Основы парадигмы структурного программирования

    Мы знаем, что идеи о структурном программировании возникли после доклада Э. Дейкстры еще в 1965 году, где он обосновал отказ от оператора GOTO. Именно этот оператор превращал программы в неструктурированные (Спагетти-код), а Дейкстра доказал, что возможно написать программы без использования этого оператора в результате чего программы станут структурными.

    Но одно дело теория, а другое практика. В этом смысле, представляет интерес рассмотреть, какая ситуация была к 1975 году. Это хорошо видно по книге Э. Йодана (). Рассмотреть это важно потому, что сейчас спустя более 30 лет, принципы уже хорошо известные тогда, сейчас переоткрываются, и возводятся в новый ранг. Но при этом теряется исторический контекст, и иерархия важности этих принципов, что первично, а что вторично. Эта ситуация аморфности очень хорошо характеризует сегодняшнее состояние программирования.

    Но что было тогда? Как описывает Йодан, все начинается с ответа на вопрос: «Что значит написать хорошую программу?». Вот первый критерий, на какие вопросы должна отвечать парадигма программирования высокого уровня. Если она не отвечает прямо на этот вопрос, а рассказывает вам как можно получить некоторые интересные характеристики вашей программы, то вы имеете дело с парадигмой низкого уровня - подходом при программировании.

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

    Примечателен, довольно характерный спор программистов:
    * Программист А: “Моя программа в десять раз быстрее вашей, и она занимает в три раза меньше памяти!”
    * Программист Б: “Да, но ваша программа не работает, а моя - работает!”

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

    Кроме того, уже тогда говорили о гибкости программы - о простоте ее изменения, расширения и модификации. Для этого необходимо постоянно отвечать на вопросы определенного вида. “Что будет, если мы захотим расширить эту таблицу?”, “Что произойдет, если однажды мы захотим определить новую программу изменений?”, “А что, если нам придется изменить формат таких-то выходных данных?”, “Что будет, если кто-то решит вводить данные в программу другим способом?”.

    Также говорили о важности спецификаций интерфейсов, т.е. формализованный подход к спецификации входов, функций и выходов, которые должны быть реализованы каждым модулем.

    Кроме того, центральное внимание уделяли размеру и неизменности модуля. Причем что касается неизменности модуля, то она рассматривалась не целиком, а с выделением отдельных факторов:
    1. Логическая структура программы, т.е. алгоритм. Если вся программа зависит от некоторого специального подхода, то в скольких модулях потребуется внести изменения при изменении алгоритма?
    2. Аргументы, или параметры, модуля. Т.е. изменение спецификации интерфейсов.
    3. Внутренние переменные таблиц и константы. Многие модули зависят от общих таблиц, если изменяется структура таких таблиц, то мы можем ожидать, что модули также изменятся.
    4. Структура и формат базы данных. В большей степени эта зависимость аналогична зависимости от общих переменных и таблиц, упомянутой выше, с той разницей, что с практической точки зрения базу данных удобнее считать независимой от программы.
    5. Модульная структура управления программой. Некоторые пишут модуль не особенно задумываясь над тем, каким образом он будет использоваться. Но если изменились требования. Какую часть логической структуры модуля нам придется изменить?

    Эти и множество других аспектов (которые мы тут не рассмотрели) в целом и формулируют представление о структурном программировании. Забота об этих аспектах и делает структурное программирование парадигмой высокого уровня.

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

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

    Но если парадигмы высокого уровня призваны отвечать на вопрос как написать хорошую программу, а появление нового технического приема, или рассмотрение новых факторов не дает выйти за границы структурного программирования (т.к. оно и останется структурным, независимо от числа приемов и факторов), то что же тогда позволит выйти за границы этой парадигмы. Действительно, как известно из науки вообще парадигмы так быстро не меняются. Научные революции случаются редко, когда предшествующая парадигма уже на практике из имеющихся теоретических воззрений просто не может объяснить происходящих явлений. Аналогичную ситуацию мы имеем при смене парадигмы со структурной до объектно-ориентированной.

    Уже признано, что причиной появления объектно-ориентированной парадигмы стала необходимость писать все более и более сложные программы, в то время как парадигма структурного программирования имеет некий предел, после которого развивать программу становится невыносимо сложно. Вот, например, что пишет Г. Шилдт:

    На каждом этапе развития программирования появлялись методы и инструментальные средства для “обуздания” растущей сложности программ. И на каждом таком этапе новый подход вбирал в себя все самое лучшее из предыдущих, знаменуя собой прогресс в программировании. Это же можно сказать и об ООП. До ООП многие проекты достигали (а иногда и превышали) предел, за которым структурный подход к программированию оказывался уже неработоспособным. Поэтому для преодоления трудностей, связанных с усложнением программ, и возникла потребность в ООП. ()

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

    Существует еще одна главная проблема: физическая ограниченность возможностей человека при работе со сложными системами. Когда мы начинаем анализировать сложную программную систему, в ней обнаруживается много составных частей, которые взаимодействуют друг с другом различными способами, причем ни сами части системы, ни способы их взаимодействия не обнаруживают никакого сходства. Это пример неорганизованной сложности. Когда мы начинаем организовывать систему в процессе ее проектирования, необходимо думать сразу о многом. К сожалению, один человек не может следить за всем этим одновременно. Эксперименты психологов, например Миллера, показывают, что максимальное количество структурных единиц информации, за которыми человеческий мозг может одновременно следить, приблизительно равно семи плюс-минус два. Таким образом, мы оказались перед серьезной дилеммой. """Сложность программных систем возрастает, но способность нашего мозга справиться с этой сложностью ограничена. Как же нам выйти из создававшегося затруднительного положения?"""

    Затем он говорит о декомпозиции:

    Декомпозиция: алгоритмическая или объектно-ориентированная? Какая декомпозиция сложной системы правильнее - по алгоритмам или по объектам? В этом вопросе есть подвох, и правильный ответ на него: важны оба аспекта. Разделение по алгоритмам концентрирует внимание на порядке происходящих событий, а разделение по объектам придает особое значение агентам, которые являются либо объектами, либо субъектами действия. Однако мы не можем сконструировать сложную систему одновременно двумя способами. Мы должны начать разделение системы либо по алгоритмам, либо по объектам, а затем, используя полученную структуру, попытаться рассмотреть проблему с другой точки зрения. Опыт показывает, что полезнее начинать с объектной декомпозиции. Такое начало поможет нам лучше справиться с приданием организованности сложности программных систем.

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

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

    Теперь, если посмотреть внимательнее, оказывается, что объектно-ориентированная парадигма есть не что иное как моделирование вообще, наиглавнейший аспект которого наиболее четко выразил С. Лем:

    Моделирование - это подражание Природе, учитывающее немногие ее свойства. Почему только немногие? Из-за нашего неумения? Нет. Прежде всего потому, что мы должны защититься от избытка информации. Такой избыток, правда, может означать и ее недоступность. Художник пишет картины, но, хотя мы могли бы с ним поговорить, мы не узнаем, как он создает свои произведения. О том, что происходит в его мозгу, когда он пишет картину, ему самому неизвестно. Информация об этом находится в его голове, но нам она недоступна. Моделируя, следует упрощать: машина, которая может написать весьма скромную картину, рассказала бы нам о материальных, то есть мозговых, основах живописи больше, чем такая совершенная «модель» художника, какой является его брат-близнец. Практика моделирования предполагает учет некоторых переменных и отказ от других. Модель и оригинал были бы тождественны, если бы процессы, происходящие в них, совпадали. Этого не происходит. Результаты развития модели отличаются от действительного развития. На это различие могут влиять три фактора: упрощенность модели по сравнению с оригиналом, свойства модели, чуждые оригиналу, и, наконец, неопределенность самого оригинала. (фрагмент произведения «Сумма технологий», Станислав Лем, 1967)

    Таким образом, С. Лем говорит о абстрагировании как основе моделирования. В тоже время абстрагирование и есть главный признак объектно-ориентированной парадигмы. Г. Буч по этому поводу пишет:

    Разумная классификация, несомненно, - часть любой науки. Михальски и Степп утверждают: «неотъемлемой задачей науки является построение содержательной классификации наблюдаемых объектов или ситуаций. Такая классификация существенно облегчает понимание основной проблемы и дальнейшее развитие научной теории». Почему же классификация так сложна? Мы объясняем это отсутствием «совершенной» классификации, хотя, естественно, одни классификации лучше других. Кумбс, Раффья и Трал утверждают, что «существует столько способов деления мира на объектные системы, сколько ученых принимается за эту задачу». Любая классификация зависит от точки зрения субъекта. Флуд и Кэрсон приводят пример: «Соединенное Королевство… экономисты могут рассматривать как экономический институт, социологи - как общество, защитники окружающей среды - как гибнущий уголок природы, американские туристы - как достопримечательность, советские руководители - как военную угрозу, наконец, наиболее романтичные из нас, британцев - как зеленые луга родины».
    """Поиск и выбор ключевых абстракций.""" Ключевая абстракция - это класс или объект, который входит в словарь проблемной области. """Самая главная ценность ключевых абстракций заключена в том, что они определяют границы нашей проблемы""": выделяют то, что входит в нашу систему и поэтому важно для нас, и устраняют лишнее. Задача выделения таких абстракций специфична для проблемной области. Как утверждает Голдберг, «правильный выбор объектов зависит от назначения приложения и степени детальности обрабатываемой информации».

    Как мы уже отмечали, определение ключевых абстракций включает в себя два процесса: открытие и изобретение. Мы открываем абстракции, слушая специалистов по предметной области: если эксперт про нее говорит, то эта абстракция обычно действительно важна. Изобретая, мы создаем новые классы и объекты, не обязательно являющиеся частью предметной области, но полезные при проектировании или реализации системы. Например, пользователь банкомата говорит «счет, снять, положить»; эти термины - часть словаря предметной области. Разработчик системы использует их, но добавляет свои, такие, как база данных, диспетчер экрана, список, очередь и так далее. Эти ключевые абстракции созданы уже не предметной областью, а проектированием.

    Наиболее мощный способ выделения ключевых абстракций - сводить задачу к уже известным классам и объектам.

    Итак, объектно-ориентированная парадигма становится парадигмой высокого уровня, и главенствует над принципами парадигмы структурного программирования, так как занимается моделированием реальности, строит модели предметных областей на языке специалистов этих областей. Если Вы этим пренебрежете ради написания хорошей программы, которую станет легко модифицировать, расширять, в которой будут четкие интерфейсы и независимые модули, вы возвратитесь на уровень парадигмы структурного программирования. Ваша программа будет всем хороша, но её нельзя будет понять, так как она не будет соответствовать реальности, она будет объяснена в терминах только известных вам, а специалист знающий предметную область не сможет без вашей помощи разобраться в программе. В конце концов, сложность будет понижаться в очень узком диапазоне, хотя вы и организовали хорошую программу. Но именно программу, а не модель. Отсутствие модели, или лишь её поверхностное представление, «взорвет» вашу хорошую программу изнутри, и не даст дальше развивать и сопровождать её в дальнейшем. Когда вы вводите классы, абстракций которых не существует, когда эти классы чисто системные и не имеют ничего общего с предметной областью, когда они введены лишь для упрощения потоков взаимодействия других классов - ваше программное обеспечение становится «с бородой», и если путем рефакторинга не следить за такими участками в один прекрасный момент развитие вашего ПО остановится, и станет не возможным - вы достигните предела структурного программирования (а вам казалось, используя классы и объекты вам это не грозит?).

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

    Да, и еще, чтобы было понятно - опубликовать я решил после дискуссий здесь Запрограммируем перцептрон Розенблатта? , где очевидным образом стало понятно, что функциональное программирование при построении плохой модели в ООП работает хуже не куда. И то, что они хвалятся супер скоростью - это фикция, на самом деле важна правильная модель. Для некоторых (не много таких задач сравнительно) функциональное программирование может быть успешным, но его не нужно использовать повсеместно, там где оно не дает ничего хорошего. Ну, или так - сможете написать обсуждаемый там кусок ТОЛЬКО в функциональном стиле, и чтобы это работало быстрее, чем с событиями ООП?

    Теги: Добавить метки

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

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

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



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

    Это были машинные коды, языки ассемблера и ранние высокоуровневые языки, вроде 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++), пространства имен, статические классы и/или динамически подключаемые библиотеки.

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

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

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