© 2018
Легалов А.И.
Во многом особенности систем программирования определяются архитектурой исполнителей, разнообразие которых порождает множество подходов к решению даже одной и той же задачи. Это позволяет использовать различные комбинации специализированных моделей и ведет к появлению разных стилей программирования, определяемых также как парадигмы.
Парадигмы занимают важное место в технологии разработки программного обеспечения. Вокруг них начинают выстраиваться и развиваться методологические концепции. Такая роль обуславливается тем, что возникающие новые идеи по созданию программ первоначально реализуются в простых инструментах, поддерживающих исследование и экспериментальную проверку выдвигаемого стиля. Чаще всего в качестве инструментов выступают языки программирования. Упомянутые исследования начинаются с написания простых программ. Лишь после обобщения первоначального опыта приходит понимание достоинств и недостатков, позволяющих перейти к формированию методологий, обеспечивающих использование парадигмы при разработке больших программных систем. Если разработанная парадигма не способна служить основой промышленной методологии, она отвергается или применяется в ограниченных масштабах.
Существуют разнообразные определения парадигм программирования. По этому вопросу трудно найти консенсус. Поэтому каждому приходится выбирать, на чьей стороне быть. Не знаю, какая из них темная, а какая светлая, но мне ближе определение, прочитанное в свое время в книгах Гради Буча [Буч92Буч Г. Объектно-ориентированное проектирование с примерами применения. /Пер. с англ. - М.: Конкорд, 1992. - 519 с., ил.] и [Буч98Буч Г. Объектно-ориентированный анализ и проектирование с примерами приложений на C++, 2-е изд./Пер. с англ. - М.: "Издательства Бином", СПб: "Невский диалект", 1998 г. - 560 с., ил.]:
Парадигма программирования – это парадигма, определяющая некоторый цельный набор идей и рекомендаций, формирующих стиль и технику написания программ. Например, в объектно-ориентированном программировании программист рассматривает программу как набор взаимодействующих объектов, тогда как в функциональном программировании программа представляется в виде цепочки вычисления функций.
В свое время оно мне показалось ближе к общему понятию парадигмы, прочитанному в англо-русско-немецко-французском толковом словаре по вычислительной технике [АРНФСАнгло-русско-немецко-французский толковый словарь по вычислительной технике и обработке данных, 4132 термина. Под. ред. А.А. Дородницына. М.: 1978. 416 с.)]:
Парадигма (от греческого παράδειγμα – пример, модель, образец) – в философии, социологии исходная концептуальная схема, модель постановки проблем и их решения, методов исследования, господствующих в течение определенного исторического периода в научном сообществе. Смена парадигм представляет собой научную революцию или эволюционный переход.
Наличие разнообразных стилей написания программ во много обусловлено гибкостью программирования, когда одни и те же идеи можно выразить различным способом. Вместе с тем реальная практика показывает, что зачастую использование соответствующего стиля программирования позволяет повысить эффективность разработки ПО в той или иной предметной области за счет большего соответствия между ее понятиями и конструкциями, предоставляемыми системами программирования.
Разделение систем программирования по парадигмам
Системы программирования, включающие языки программирования, являются основным инструментом, используемым для написания, преобразования и выполнения программ программ, что определяет их значимость в достижении критериев качества. Анализ организации систем программирования позволяет выделить специфику инструментальных средств, поддерживающих разработку программных систем.
Классификация систем программирования по парадигмам является одной из наиболее популярных. Она позволяет осуществить достаточно четкую градацию, опираясь на основные отличительные признаки. Буч [Буч98Буч Г. Объектно-ориентированный анализ и проектирование с примерами приложений на C++, 2-е изд./Пер. с англ. - М.: "Издательства Бином", СПб: "Невский диалект", 1998 г. - 560 с., ил.], ссылаясь в своих книгах Боброва и Стетика, приводит пять основных стилей (таблица 1).
Таблица 1 - Основные стили программирования
Название стиля |
Основополагающие абстракции |
Логико-ориентированный |
Цели, часто выраженные в терминах исчисления предикатов |
Ориентированный на правила |
Правила «если-то» |
Ориентированный на ограничения |
Инвариантные отношения |
Процедурный |
Алгоритмы, абстрактные типы данных |
Объектно-ориентированный |
Классы и объекты |
Для некоторых из представленных вариантов можно провести дополнительную градацию. В частности, процедурно-ориентированный стиль содержит императивную и функциональную парадигмы программирования.
Императивное программирование базируется на основе автоматной модели вычислителя, разделяющей абстракции состояния и поведения. При этом программа рассматривается как процесс изменения состояния путем выполнения отдельных команд. Примерами таких вычислителей являются машина Тьюринга, фон-неймановская архитектура. Различные направления императивного программирования получили широкое развитие. Из него, например, выросло структурное программирование.
Функциональное программирование опирается на теорию рекурсивных функций. Акцент делается на зависимость между функциями по данным. Модель состояний при этом практически игнорируется. В целом программу можно написать без явного указания последовательности вычислений, которая определяется как особенностями данных, так и тем, каким образом неявное управление вычислениями преобразуется системой программирования в явное при выполнении в реальных императивных исполнителях.
Перерастание парадигмы в методологию определяется различными факторами, среди которых можно выделить:
эффективность реализации инструментальных средств, поддерживающих исследуемую парадигму;
удобство в использовании на этапе проектирования;
эффективная поддержка процесса разработки больших программ;
генерация эффективного выходного представления;
эффективное выполнение полученной программы.
Из стилей, представленных в таблице 1, только процедурный и объектно-ориентированный оказались в настоящее время жизнеспособными для разработки больших программных систем. И только ООП послужило основой для разработки всеобъемлющей и сквозной методологии проектирования. Такая ситуация возникла из-за ряда особенностей, присущих различным парадигмам. Большинство из них, в конечном итоге, не смогли удовлетворить требованиям, предъявляемым к промышленным системам, так как не обеспечили комплексную поддержку разнообразных критериев качества. Поэтому, использование многих стилей в настоящий момент ограничено научными исследованиями, быстрой разработкой прототипов, учебными задачами.
Приведенная классификация, как и многи другие, построена по эмпирическому принципу, предполагающему смещения акцента на одну из специфических характеристик. При разработке систем программирования достаточно часто происходит совместная реализация нескольких парадигм, то есть, используется мультипарадигменный стиль. Подобное смешение обуславливается двумя факторами.
Во-первых, различные ключевые характеристики, акцентируют внимание на несвязанных между собою параметрах. Например, объектная ориентированность, модульность и абстрактные типы характеризуют разные подходы к конструированию программных объектов и конкурируют между собой. С другой стороны существуют различные методы алгоритмизации задач (императивный, функциональный, автоматный, логический), допускающие интеграцию с различными конструктивными элементами. Поэтому возможные сочетания невзаимосвязанных характеристик позволяют создавать системы программирования, обладающие необходимой функциональной и конструктивной полнотой для решения любых задач.
Во-вторых, особенности ряда критериев, размещаемых в одной группе, с неодинаковой эффективностью обеспечивают решение различных классов задач. Существуют языки программирования, которые, несмотря на избыточность, поддерживают различные методы конструирования программных объектов и способы описания алгоритмов. Например, ОО и процедурный подход сочетаются в C++ и Delphi, функциональное и ОО программирование одновременно могут использоваться при программировании на языках Caml и Clean. Язык программирования CLOS позволяет применять функциональный, императивный и ОО стили. Одновременное присутствие нескольких парадигм обеспечивает большую гибкость при разработке программ.
Дополнительные характеристики парадигм программирования
Независимо от используемых подходов, системы программирования обеспечивают техническую поддержку процесса разработки, который характеризуется использованием ряда общих принципов, обуславливаемых целью: создание программы, допускающей дальнейшее выполнение непосредственно или после цепочки формальных и автоматических преобразований. Вместе с тем, представленная классификация систем программирования, опирающаяся на парадигмы, не позволяет объективно и всесторонне оценить параметры, определяющие различные способы написания программ. Это затрудняет:
исследование критериев качества программного обеспечения;
создание моделей для оценки различных характеристик систем программирования;
разработку новых методов построения программ.
При исследовании разнообразных критериев качества программ нужно опираться не только на общие черты, определяемые парадигмами. Необходимо выделить характеристики, обеспечивающие независимый анализ требуемых характеристик. В этом случае формирование общего восприятии анализируемой системы может быть достигнуто путем комбинирования альтернативных критериев. Подобное разбиение можно провести по следующим составляющим:
методам алгоритмизации решаемой задачи;
методам управления вычислениями;
способам организации программных объектов и формированию отношений между ними;
специфике процессов преобразования модели исполнителя, заданной системой программирования, в модель исполнителя, осуществляющего реальное выполнение программ (способы выполнения программ).
Каждая из представленных характеристик оказывает определенное влияние на особенности разрабатываемых программ.
Методы алгоритмизации
Описание алгоритма решаемой задачи является одной из основных задач программирования. Разнообразие методов алгоритмизации порождает множество поведенческих парадигм, каждая из которых характеризуется своей спецификой описания процесса обработки данных. Например (но далеко не все):
императивный стиль определяет исполнителя на основе традиционной фон-неймановской архитектуры, непосредственно исполняющего команды, заданные программистом (при этом команды явно связаны между собой только по управлению, а зависимость по данным выстраивается на основе образных ассоциаций программиста);
автоматное программирование является подмножеством императивного стиля, акцентируясь при этом на модели состояний, что ведет к абстрагированию на этапе разработки программы от операций, связанных с обработкой данных (это ускоряет построение общей схемы логического управления алгоритмом).
функциональное программирование опирается на теорию рекурсивных функций и описывает процесс управления в виде отношений между функциями (управление явно не задается и определяется зависимостью между функций по готовности результатов);
программирование, управляемое потоками данных, как и функциональное программирование, использует отношение между функциями и операциями, но непосредственно ориентировано на выполнение операций по готовности данных (в отличие от функционального программирование основной упор делается на продвижение потоков, которые одновременно и параллельно запускают не связанные между собой операторы);
логическое программирование опирается на логику исчисления предикатов, которая обуславливает организацию алгоритма, непосредственно не описывающую вычисления (используемая для его выполнения машина логического вывода первоначально осуществляет анализ правил, задающих различные отношения, выбирая среди них на выполнение те, которые соответствуют заданным условиям).
Каждый из представленных стилей определяет специфическую интерпретацию понятий, связанных с поведением программы и обуславливает конкретные методы и приемы построения алгоритмов, которые могут сильно отличаться даже для одной и той же решаемой задачи.
Стратегии управления вычислениями
Методы алгоритмизации решаемой задачи тесно связаны с походами к управлению вычислениями, разнообразие которых обуславливается способами описания параллельных вычислений. Управление может варьироваться от последовательного до задания максимального параллелизма. Оно может задаваться явно программистом или неявно, когда используются отношения между данными и автоматическое управление ресурсами. Все разнообразие методов управления раскрывается как через архитектуры вычислительных систем, так и языков последовательного и параллельного программирования.
Используемые стратегии управления вычислениями сильно влияют на переносимость параллельных программ, так как именно они непосредственно отражают все ограничения, присущие как реальной вычислительной системе, так и виртуальной машине, определяющей особенности исполнителя конкретного языка программирования.
Организация программных объектов
Разработка больших программных систем изначально опиралась на различные методы декомпозиции. В ходе исторического развития были опробованы различные схемы компоновки структур данных и кода программы. Ряд их используется и в настоящее время. Наиболее типичными примерами являются:
модульная структура;
абстрактные типы данных, классы;
процедуры (подпрограммы, функции, методы);
интерфейсы.
В отличие от методов алгоритмизации, методы организации программных объектов не определяют процесс выполнения решаемой задачи. Однако они оказывают существенное влияние на такие характеристики, как повторное использование кода, эволюционное расширение в ходе добавления в программу новой функциональности. Организация программных объектов оказывает существенную роль на разработку больших программных систем. Именно она обуславливает основные тенденции в современном программировании, в частности, популярность дальнейшее развитие объектно-ориентированного подхода.
Говоря об организации программных объектов, можно отметить, что речь идет о небольшом числе форм их конструирования. Это агрегаты и обобщения, связанные между собой непосредственно, косвенно или с использованием ассоциаций. Однако в настоящее время существуют разнообразные альтернативные подходы к формированию этих конструкций, каждый из которых обеспечивает эффективную поддержку тех или иных критериев качества. Наряду с традиционными формами конструирования, опирающимися на вложенность конструктивов, сейчас широко используются подходы, обеспечивающие поддержку полиморфизма в той или иной форме, что, в свою очередь повышает гибкость процесса разработки программного обеспечения.
Способы выполнения программ
Современные программные системы зачастую являют многомодульными конструкциями. Существуют различные технологии трансляции, компоновки и выполнения таких программ, что также ведет появлению разнообразных стилей программирования. В частности, использование сборки множества модулей в один монолитный конструктив в ходе статической компоновки позволяет не задумываться о том, каким образом осуществлять связь между различными программными объектами. С другой стороны динамическая подгрузка модулей во время исполнения требует написания дополнительного кода, хотя и обеспечивает большую гибкость. Таких вариантов организации выполнения программы очень много и каждый из них требует учета тех или иных особенностей, влияя тем самым на стиль программирования.
Классификация систем программирования по представленным характеристикам
К четырем представленным характеристикам, по всей видмости, еще можно что-то добавить. Однако даже и в этом случае на ту или иную систему програмирования можно посмотреть исходя из ее представления в виде следующего вектора:
P = (A, C, D, E),
где P - парадигматическая характеристика системы программирования; A - методы алгоритмизации, используемые в системе программирования (может использоваться несколько методов); D - способы конструирования программных объектов; E - способы выполнения программы.
Исходя из этого множестов разнообразных систем программирования можно "разложить" по клеткам четырех мерного пространства, размер которого определяется произведением мощностей каждой из характеристик:
S = |A| × |C| × |D| × |E|.
Это "разложение" позволяет более гибко охарактеризовать различные системы программирования как совокупность парадигм с разными характеристиками, включая и наличие нескольких парадигм одного типа.
Список используемых источников
[Буч92] Буч Г. Объектно-ориентированное проектирование с примерами применения. /Пер. с англ. - М.: Конкорд, 1992. - 519 с., ил.
[Буч98] Буч Г. Объектно-ориентированный анализ и проектирование с примерами приложений на C++, 2-е изд./Пер. с англ. - М.: "Издательства Бином", СПб: "Невский диалект", 1998 г. - 560 с., ил.
[АРНФС] Англо-русско-немецко-французский толковый словарь по вычислительной технике и обработке данных, 4132 термина. Под. ред. А.А. Дородницына. М.: 1978. 416 с.)
|