Проблемный ряд парадигм и языков программирования
Прагматический характер информатики предполагает постоянное сравнение ее составляющих. Остается то, что в прагматическом отношении наиболее эффективно: все остальное либо выбраковывается, либо переосмысливается и в результате обновляется. В этой связи особый интерес представляют парадигмы программирования, поскольку их состояние в значительной степени определяет качество программного обеспечения. В концептуальном отношении парадигмы программирования предшествуют языкам программирования и программам. Таблица 4.5 дает представление о парадигмах программирования, число которых не установлено точно.
Таблица 4.5. Парадигмы программирования
Парадигма |
Основные идеи |
|||
1 |
Автоматно-ориентированное программирование |
Программа или ее фрагмент осмысливаются как модель какого-либо формального автомата |
||
2 |
Императивное программирование |
Процесс вычисления описывается в виде инструкций, изменяющих состояние программы |
||
3 |
Процедурное программирование |
Задается последовательность операторов (инструкций), определяющих процедуру решения задачи |
||
4 |
Функциональное программирование |
Процесс вычисления трактуется как определение значений функций в математическом понимании последних (в отличие от функций как подпрограмм в процедурном программировании; |
||
5 |
Логическое программирование |
Решающее значение придается теории и аппарату математической логики |
||
6 |
Декларативное программирование |
Описывает нечто, а не его создание. Противопоставляется императивному программированию |
||
7 |
Структурное программирование |
Программа проектируется в виде структуры блоков |
|
|
8 |
Объектно-ориентированное программирование |
Решающее значение придается концепту объекта, который понимается как неделимое целое, принадлежащее классу и обладающее определенной формой поведения |
|
|
9 |
Аспектно-ориентированное программирование |
Аспект понимается как модуль или класс, реализующий сквозную функциональность |
|
|
10 |
Аппликативное программирование |
Систематическое осуществление применения одного объекта к другому |
|
|
11 |
Событийно-ориентированное программирование |
Выбирается главный цикл приложения |
|
|
Введение концепта "парадигма программирования" связано с необходимостью осознать вариабельность языков высокой степени концептуальности, или, как часто выражаются, абстрактности. В период доминирования машинных кодов, ассемблеров и ранних компиляторов, потребность в концепте парадигмы программирования не ощущалась. Все, что касалось программирования, казалось относительно простым и понятным. После появления зоопарка языков программирования ситуация кардинальным образом изменилась. В 1960-е гг. были введены представления об императивном, функциональном и процедурном программировании, в 1970-е - о структурном программировании, в 1980-е - об объектно-ориентированном программировании, которое во многих отношениях до сих пор удерживает пальму первенства.
Концепт "парадигма программирования" в 1979 г. в информатику ввел американский ученый Р. Флойд1. При этом он трижды процитировал философа Т. Куна, который известен в качестве основателя учения о парадигмах в рамках философии науки. Но аргументация Флойда существенно отличается от доводов Куна, который в основном обыгрывал синонимичность терминов "парадигма" и "образец". Согласно Куну, парадигма является образцом, который позволяет разрешать головоломки. Флойд же связывал концепт парадигмы программирования по преимуществу с двумя другими факторами: во-первых, со своеобразием языков программирования, а во-вторых, с необходимостью выделения концептуальных оснований предпринимаемых программистом усилий. Следует отдать должное Р. Флойду: ему удалось довольно точно определить эпистемологический статус парадигм программирования. Прагматический аспект дела считался достаточно очевидным: парадигмы нуждаются в постоянном совершенствовании.
Парадигмы в информатике выступают в качестве концептов, напоминающих по своей природе принципы. Парадигмы программирования, с одной стороны, обладают весьма общим ОГЛАВЛЕНИЕм, а с другой - дают начало цепям трансдукции, которые, в частности, приводят непосредственно к программам. Если бы Р. Флойд в своем анализе ориентировался не столько на концепт куновской парадигмы, сколько на понятие научного принципа, то, надо думать, он не остался бы в проигрыше. В строго научном смысле слова парадигма программирования является не неким образцом, как это предполагается этимологией греческого слова, а именно научным принципом.
Основные подходы к интерпретации парадигм программирования. Рассмотрим теперь вопрос о возможности упорядочения принципов программирования. Нетрудно заметить, что каждый из них обладает относительной самостоятельностью, и лишь все вместе они образуют единое целое. В табл. 4.5 указано 11 парадигм. Такой список избыточен. Его целесообразно сократить, выделяя в более отчетливом виде актуальные для анализа информатики концептуальные единицы. В этой связи резонно обратиться к нескольким подходам, каждый из которых содержит несколько парадигм:
(2) Алгоритмический подход (ориентированный на алгоритмы).
(3) Логико-математический подход (ориентированный на логико-математические средства). Он включает функциональную и логическую парадигмы.
(4) Процедурный подход. Обычно в эту рубрику включают наряду с процедурной также императивную парадигму. Его вершиной стало структурное программирование.
(5) Объектно-ориентированный подход, который восходит к структурной парадигме, связав воедино данные и программы, объекты и процессы. В своих спецификациях этот подход включает аспектное и событийное программирование. Что касается аппликативной парадигмы, то она органична как для объектно-ориентированного, так и для логико-математического подхода.
Нетрудно видеть, что многозвенный концептуальный переход
знаменует собой вполне определенный проблемный ряд возрастающей концептуальности. В историческом плане тот или иной культивируемый подход всегда подвергался некой модификации, что приводило к появлению принципиально новой концептуальной единицы. Читатель детально ознакомлен с необходимостью сопровождения проблемного ряда интерпретационным строем. Надо полагать, для него не является неожиданностью интерпретационный строй
который означает, что при желании выяснить смысл того или иного подхода необходимо руководствоваться в первую очередь объектно-ориентированным подходом. Довольно часто первые три подхода из табл. 4.5 считаются всего лишь прелюдией к современному состоянию программирования. В таком случае объектно-ориентированный подход сравнивается с процедурным.
Объектно-ориентированное программирование.
В ходе неоднократных попыток обособить тот или иной подход от объектно-ориентированного всегда выяснялось, что такого рода изоляция если и продуктивна, то лишь до определенных границ. Аппаратный и алгоритмический подходы позволяют рассмотреть актуальные примеры компьютерной вычислимости, но не создать ее всеобъемлющую теорию. Логико-математический подход предлагает высокие образцы концептуальности, но им явно недостает компьютерной конкретики. Процедурный подход встречается с существенными трудностями при необходимости учета специфики и, следовательно, структуры данных. Если этим учетом можно пренебречь, то процедурный подход оказывается вполне уместным. Таким образом, наиболее емким в концептуальном отношении является объектно-ориентированный подход, равно как и та парадигма, которая составляет его основное ОГЛАВЛЕНИЕ.
Сущность этой парадигмы в деталях рассмотрел американский исследователь Г. Буч. В объектном программировании первостепенное значение придается концептам объекта, класса и суперкласса (родительского класса). Объект является экземпляром класса, а тот, в свою очередь, суперкласса. Не без оснований считается, что таким образом концептуально воспроизводится иерархическое строение любых систем. Что касается алгоритмов, то они относятся к объектам. Используя лингвистические термины, можно сказать, что смысл глагола определяется тем подлежащим, с которым он соотносится. Мир состоит из вещей и их проявлений, в качестве которых выступают действия и поведение. Все объекты данного класса ведут себя одинаковым образом. Но что такое объект?
Повсеместно распространено убеждение, согласно которому объектом является нечто, что определено посредством его существенных признаков. Это означает, что продолжает господствовать довольно наивная теория абстракций, которая не раз подвергалась острой критике. Объект - это то, что обладает признаками, а сами признаки определяются исходя из содержания соответствующих наук. Когда данное обстоятельство игнорируется, то приходится заново изобретать велосипед.
Суть объектно-ориентированного программирования состоит не в теории абстракций, а в переходе на научно оправданные концептуальные позиции. Наряду с концептом абстракции энтузиасты объектно-ориентированного программирования придают большое значение концептам инкапсуляции, наследования и полиморфизма.
Инкапсуляция состоит в переносе внимания с устройства объекта на его внешние отношения. Предметом внимания является не внутреннее устройство объекта, а его внешнее поведение. Имея это в виду, часто говорят, что внутреннее ОГЛАВЛЕНИЕ объекта, будучи помещенным в капсулу, скрывается от пользователя, который взаимодействует с объектом посредством интерфейса. Концепт инкапсуляции фиксирует, во-первых, дискретность информационных систем, различие внутри-объекта и вне-объекта, а во-вторых, необходимость и плодотворность различных способов анализа и поведения, реализуемых как программистом, так и пользователем.
Наследование касается отношения между классами. Оно имеет место в случае, если новый класс наследует свойства и методы класса-предка, т.е. к характеристикам класса-предка добавляются новые черты. Наследование призвано отобразить иерархичность мира информатики: оно всегда имеет некоторые границы.
Полиморфизм реализуется как управление разными типами данных посредством одного и того же интерфейса. Это возможно, если в классе-потомке изменение реализации метода класса-предка сопровождается сохранением сигнатуры последнего, в частности типов аргументов и их количества.
Таким образом, основное достижение объектно-ориентированного подхода состоит в его концептуальной чистоте, прекрасно сопряженной с уроками концептуального анализа из различных наук.
Критика объектно-ориентированного подхода
В научной литературе встречается огромное число критических замечаний в адрес объектно-ориентированного подхода. Однако чаще всего критика относится не к его концептуальным основаниям, которые интересуют нас в первую очередь. Как правило, критики сетуют на неудачное использование потенциала объектно-ориентированного программирования. Но, пожалуй, самая резкая оценка содержится в статье Ричарда Гэбриэла, который утверждает, что "объектная парадигма провалилась". Он заканчивает свою статью следующим выводом: "В конце концов, никто не агитирует менять то, как мы работаем с объектами и объектно-ориентированными языками. Нет, просто необходимо разнообразие, необходимо работать над новыми парадигмами, чтобы "дать расцветать тысячам цветов". Самовосстанавливающиеся, распределенные и сложные системы, самоорганизующиеся, адаптирующиеся, растущие по крупицам как живые организмы, использующие статистическое поведение, эволюционирующие, использующие избыточность ради безаварийности - системы, в основе которых могут быть еще сотни различных перспективных идей и подходов, о которых мы еще и не думали, - все должно быть позволено и поддержано для движения вперед. Сейчас самое время для определения новой и смены старой парадигмы. Часто новое вообще не выглядит научно, или рационально, статьи и разговоры, объясняющие новые
идеи могут звучать как пропаганда, как фантастика, или даже как поэзия; действительность же играет большую роль, чем теоремы или точные результаты. Можно сказать, что это не будет наукой в нашем привычном понимании. В свете всего вышесказанного, можно с уверенностью заявить, что объектная парадигма обманула наши ожидания".
Как видим, Ричард Гэбриэл не находит альтернативы объектно-ориентированному подходу. Он вполне правомерно выступает против попыток насаждения универсальной точки зрения. Разнообразие, конечно, необходимо, но при этом, как очевидно, не стоит ожидать отречения от старого. Было бы весьма опрометчиво в предвкушении нового отказаться от тех концептуальных достижений, которых добилась наука сегодняшнего дня. Гай Стал в ответ на критику Гэбриэла имел все основания заявить следующее: "Разумеется, объекты не решают все проблемы программирования. Например, они не обеспечивают полиморфического абстрагирования типов (т.е. настраиваемых типов). Они не обеспечивают синтаксического абстрагирования (т.е. макросов). Процедурное программирование по-прежнему используется при кодировании методов. Но заявлять, что объекты провалились, поскольку они не решают все возможные проблемы, - это все равно, что говорить, что углеводы провалились, поскольку вы не можете жить на чистом сахаре. Объектно-ориентированное программирование напоминает деньги из старой шутки - это, может быть, и не все, но на голову обгоняет все, что может находиться на втором месте".
Завершая краткую характеристику объектно-ориентированного подхода, отметим, что его название способно ввести в заблуждение. Можно подумать, что речь идет об объектах в том их виде, в котором они встречаются в реальном мире. Но в таком случае объектам следовало бы противопоставлять язык и ментальность. В действительности же акцент делается не на онтологии или, по крайней мере, далеко не только на ней одной. Строго говоря, речь идет о концептуально адекватном воспроизведении мира информатики.
Языки программирования. Подходы и принципы программирования определяют возможность конструирования различных семейств языков информатики. Поскольку парадигмы программирования образуют восходящую линию концептуальности, то неудивительно, что большинство современных языков программирования мультипарадигмальны (табл. 4.6).
Таблица 4.6. Парадигмальность языков программирования
Интересно отметить, что языки программирования образуют некоторые семейства, каждое из которых обладает определенной направленностью. В простейшем случае ее можно изобразить в виде линейной структуры. Однако чаще всего родословная языков программирования имеет довольно ветвистую древесную структуру, при этом развитый язык программирования всегда является итогом значительного роста информационного знания.
Пример проблемного ряда языка программирования
Руководствуясь таблицей развития языков программирования, составленной Э. Левенецом2, представим в сокращенном виде родословную самого популярного на сегодняшний день языка С#:
Налицо не что иное, как вполне определенный проблемный ряд. Каждый последующий язык превосходит предыдущий по некоторым параметрам. Если бы дела обстояли по-другому, то вообще не было бы необходимости в использовании новых языков.
Между проблемными рядами языков программирования существуют поперечные связи: они эволюционируют не независимо друг от друга. Например, язык Ruby (1993) вобрал многие идеи, первоначально появившиеся в языках CLU (1974), Smalltalk (1980), Common USP (1984), Python (1991).
Языки программирования специфицируются не только в соответствии с ОГЛАВЛЕНИЕм определенных парадигм, но и по типам задач, среди которых особенно часто встречаются: 1) параллельные вычисления; 2) физико-математические расчеты; 3) вопросы искусственного интеллекта; 4) проблемы, связанные с разработкой интерфейса; 5) проектирование программ-оболочек и систем; 6) оформление документов и разработка баз данных.
Имея в виду метод концептуальной трансдукции, не без удовлетворения отмечаем, что в информатике она представлена необыкновенно выразительно. В любой научной теории обнаруживаются многочисленные проблемные ряды, но не столько и не в таком ярком виде, как в информатике, в частности в нарастающем потоке языков программирования. Концептуальная трансдукция в информатике начинается с образцов вычислений, приобретает большую определенность в парадигмах программирования, а затем выливается в половодье языков программирования, где отчетливо просматриваются отдельные потоки. Таким образом, в целом программирование выступает как мощный поток концептуальной трансдукции, началом которого являются определенные принципы, сосредоточенные в подходах, часто называемых парадигмами, и разбивающийся затем на множество течений, образующих проблемные ряды и строи.
Выводы
1. Смысл парадигм программирования переносится на языки программирования, которые также образуют проблемные и интерпретационные ряды.