Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Стили и методы программирования. Учебное пособие для СПО
.pdf
оставил от Red, Blue и Yellow, но чуть-чуть "пожалел" Green, доказывая,
что все недостатки языка связаны с несвободой в выборе решений,
обусловленных жестко фиксированными требованиями: там, где авторы
могли бы решать какие-либо проблемы по-своему, они были
вынуждены идти на поводу у априорных предписаний. Тем не менее
Green стал приемлемым вариантом и получил одобрение. Как оказалось,
это был единственный из финалистов язык, предложенный не
американцами. Конкурсная комиссия утвердила его в качестве единого
официального языка Министерства обороны США для разработки
программ для встроенных систем и дала ему имя Ada — в честь Ады
Августы Лавлейс, дочери Байрона и ученицы Бэббиджа — первой в
истории программистки.
Отметим, что успеха разработчики языка добились благодаря акценту на
концептуальную целостность — именно это выделяло Green среди
конкурентов. Заметим, что в ходе последующего развития в язык Ada
стали включать новые средства в угоду появившимся пользователям. В
результате к концу девяностых годов Ada по стилю построения стала
подобна PL/1: в ней есть средства поддержки всего, что можно найти в
работе программистов в конце XX века. Как отмечал известный
советский программист В. Ш. Кауфман, язык Ada 9х можно
рассматривать как добротную энциклопедию программистского знания
и опыта, но никак не в качестве инструмента, ориентированного на
пользователя.
9. Объектно-ориентированные языки. Последним достижением в
области программистского языкотворчества считается поддержка
объектно-ориентированной методологии. Эта сфера интересует многих
разработчиков языков начиная с восьмидесятых годов. Первым
проектом, провозгласившим принцип перехода от пассивных данных к
активным объектам, стал Smalltalk. В этом языке объектам
предоставляется возможность действовать в ответ на получаемые ими
сообщения без каких бы то ни было иных способов активизации
действий. Эта возможность реализована в рамках идеи динамической
типизации (в отличие от статической типизации, тип выражения может
в определенных пределах вычисляться наряду с его значением). В
качестве наглядной демонстрации мощи идеи была предложена система
программирования Smalltalk-80 с очень богатой библиотечной
поддержкой конструирования графических интерфейсов.
Стили и методы программированияНепейвода Н.Н.
41

Smalltalk — последний крупный проект, который был представлен на
всестороннее обсуждение программистской общественностью. В
результате таких обсуждений выяснилось, что нужно для поддержки
объектной ориентированности в языках промышленного производства
программ. Такие языки появились достаточно скоро.
Заметными объектными языками стали Turbo Pascal версий с 5.5 до 7.0
и Object Pascal системы Delphi.
Общим для промышленного развития линии языка Smalltalk является
возврат к статическим типам данных, повышенное внимание к
вопросам защиты. Появились системы программирования, приемлемые
по эффективности объектного кода и удовлетворяющие требованиям
технологичного программирования. Однако, как это обычно бывает с
производственными системами, на смену аналитическим
исследованиям границ применимости и роли языка пришли реклама
достоинств и замалчивание недостатков.
10. Язык C++. Наибольшее распространение из объектноориентированных языков получил С++, по-видимому, из-за огромной
популярности С.
C++ был создан в конце 80-х гг., он практически являлся расширением
C. В отличие от языков семейства Simula, в С++ воплощались не столько
концепции, сколько конкретные, полезные для его создателей, приемы.
Язык С++ по конструкции намного сложнее С, а определение его
производит впечатление еще большей эклектичности. Но С++, усугубив
недостатки С с точки зрения человека, сохранил при колоссальном
расширении возможностей языка все достоинства С, касающиеся
машинной ориентированности и эффективности.
С++ отличается прежде всего значительным усилением системы
описаний (объектно-ориентированные возможности являются одним
из наиболее применяемых расширений)
10)
.
Еще более укрепляют позиции языка С++ многие современные
инструментальные системы, создававшиеся на нем без учета
потребностей других языковых средств. В частности, системы работы с
динамически подключаемыми программами ( middleware ) CORBA и
COM практически требуют, чтобы программа, к ним обращающаяся,
Стили и методы программированияНепейвода Н.Н.
42

была написана на С++, поскольку вся система интерфейсов
ориентирована на типы данных этого языка и порою даже на
конкретные их представления.
11. Язык Java. Заметным этапом в развитии объектноориентированного подхода стало появление языка Java, который был
предложен как средство программирования не для отдельного
компьютера, а сразу для всех машин, имеющих реализацию так
называемой Java -машины — исполнителя программ на
промежуточном языке более высокого уровня, нежели командный язык
обычных машин. Иными словами, реализуется система
программирования с явно определенным промежуточным языком.
Другая особенность Java -проекта — его ориентация на Интернетпрограммирование: поддерживается возможность построения
приложений, работающих сразу на нескольких машинах.
Схема трансляции с выделенным промежуточным языком, не
зависящим от исходного языка, не нова. В шестидесятые годы ее
пытались применять для сокращения расходов на разработку
трансляторов (например, в США в качестве промежуточного языка был
разработан язык Uncol, в Советском Союзе для тех же целей предлагался
язык АЛМО).
Пусть требуется реализация m языков на n машинах. В схеме без
промежуточного языка в этом случае нужно запрограммировать m x n
трансляторов, тогда как использование такого языка позволяет
сократить это число до m + n: для каждого языка пишется транслятор в
промежуточный язык ( m ) и для каждой машины создается транслятор
или интерпретатор промежуточного языка ( n ). Можно предположить,
что затраты на 'половинки' трансляторов сократятся. Схема может быть
реализована, если удается построить промежуточный язык,
удовлетворяющий следующим условиям:
1. все реализуемые языки можно вложить в промежуточный язык, т.
е. их модели вычислений совместимы;
2. все целевые машины можно непротиворечиво представить в
одной модели вычислений промежуточного языка так, чтобы
трансляция программ для этой общей модели давала бы
эффективный код для конкретных вычислителей.
Стили и методы программированияНепейвода Н.Н.
43

Выполнить эти условия весьма сложно даже для близких языков и
машин, близких по архитектуре. Затраты на решение этих задач часто
неизмеримо и неоправданно превышают стоимость пресловутых m x
n трансляторов, поэтому после серии экспериментальных проектов
идея промежуточного языка была предана забвению. В проекте Java она
возродилась (правда, в урезанном до одного языка варианте) благодаря
почти унифицированной архитектуре массовых компьютеров и
значительному росту технических возможностей машин.
Именно эти дополнительные условия, а также квалифицированное
сужение исходного языка С++, позволили воплотить старую идею в
промышленной разработке
11)
.
В контексте обсуждения традиционности языков необходимо
рассмотреть вопрос о том, насколько далеко язык Java и Java -машина
отходят от традиционной модели вычислений. Совместная разработка
этих двух компонентов системы программирования для нового языка
позволила прийти к достаточно практичным компромиссам,
удовлетворить условиям выбранной схемы реализации, о которых шла
речь выше.
Условие (1) выполняется почти автоматически, и можно сосредоточить
внимание на том, чтобы обеспечить наиболее рациональное вложение
модели вычислений языка в модель машины. Что касается условия (2),
то здесь ставка делалась на фактическое сходство архитектуры
конкретных вычислителей, для которой уже накоплен опыт
программистских решений во многих типовых ситуациях. В результате
отход от традиционной модели вычислений в Java -системе хотя и
заметен, но не столь значителен. Достаточно сказать, что Java-машина
построена на принципах, предложенных еще в 1963 году для
организации вычислений в рабочей программе Ветстоунского
компилятора для Algol 60
12)
[24].
Важным новым качеством Java -машины является поддержка работы
программиста с потенциально неограниченной памятью. При
выполнении конкретной программы на языке Java можно не заботиться
о том, что какая-то часть памяти перестает быть нужной. Система
программирования сама сделает так, что та память, которая оказалась
недоступной, а значит, ненужной, возвращается для использования в
Стили и методы программированияНепейвода Н.Н.
44

новых запросах. Такие ситуации выявляются в процессе вычислений,
когда фактические ресурсы, предоставляемые для размещения данных,
требуется пополнить для переиспользования. В угоду этому соглашению
отказались от ряда приемов организации ручного переиспользования
памяти, необходимых, например, при программировании на С.
Модель вычислений Java в точности соответствует тому, что требуется
от объектно-ориентированного программирования: активность памяти
на уровне методов объектов, совместное описание данных и программ
методов, отделение предоставляемых средств от их реализации. Все это
сочетается с традиционной схемой управления вычислениями при
описании алгоритмов обработки.
Следует отметить, что разработчики языка не стали включать в него
средства, с трудом укладывающиеся в концептуальную схему Java машины и обычно предоставляемые через довольно произвольные
реализационные соглашения (как, например, в С++). Ориентация Java машины на классическую со времен Algol 60 схему организации
вычислений, повлияла на язык в том отношении, что все, выходящее за
рамки принятой модели, представлено таким образом, чтобы это можно
было вычислить в период трансляции. К примеру, проблемы
статической типизации в данном языке решены радикально: в нем
просто нет средств конструирования структурных типов, отличных от
классов объектов. В результате язык стал лаконичнее, например, по
сравнению с С++.
Для первого опыта Java достаточно гармонично соединила ряд
нововведений, которые в разрозненном виде появлялись в различных
языках, и которые в совокупности повышают уровень исходных
понятий примерно до второго типа в иерархии типов.
Программирование на Java принципиально отходит от ориентации на
особенности конкретных вычислителей. Остается лишь предположить
(далеко не всегда оправданно!), что используемые машины выполняют
требуемые действия с приемлемым уровнем эффективности.
В значительной степени для того, чтобы перехватить инициативу у
языка Java, и был создан C#, эффективно работающий прежде всего с
системами middleware, и стремящийся сохранить в новой области
эффективность C /C++. Для наших целей в большинстве случаев
Стили и методы программированияНепейвода Н.Н.
45

различия между С++ и С# несущественны.
Как видим, традиционные языки прошли путь серьезной эволюции.
Посмотрим, как трансформируются традиционные принципы
вычислений при использовании объектной модели. Очевидно, что
отход от однородности памяти для этой модели более радикален,
нежели, к примеру, в языке Pascal. Если рассматривать объекты как
хранимые в памяти данные, то за счет связанности этих данных с
программами (методами объектов) память в объектной модели
приобретает активность. На концептуальном уровне рассмотрения
можно увидеть, что модернизируется управление: объект сам знает,
какую программу-метод нужно активизировать, чтобы выполнить то
или иное действие. Несомненно, все это повышает гибкость
программирования, способствует расширению возможности отхода от
традиционного взгляда на программу как на автомат, выполняющий
предписания-команды. Однако на уровне реализации программметодов все остается по-старому: то же последовательное выполнение
операторов, те же подходы к разветвлениям вычислений и к
организации циклической обработки.
Более того, последовательный характер вычислений остается и при
задании взаимодействия объектов. Следовательно, объектный подход,
хотя и способствует взгляду на вычислительные процессы,
отличающемуся от традиционного стиля, сам по себе не приводит к
смене базовой модели вычислений.
Объектно-ориентированный подход применяется в настоящее время для
организации вычислений на основе моделей, отличных от
традиционных. При этом совершенно не принимается во внимание
концептуальная совместимость объектно-ориентированного подхода с
новым базисом и относительный уровень базиса и надстройки. Пример
рассматривается в главе, посвященной функциональному
программированию.
1)
Даже в семействе С слишком необычные приведения
рассматриваются всеми нынешними трансляторами как события,
требующие выдачи предупреждений программисту.
2)
Хакерство — неестественное применение конструкций, а также
использование недокументированных возможностей либо явных
Стили и методы программированияНепейвода Н.Н.
46

недоработок языка.
3)
Удивительно, что и сегодня, в XXI веке, появляются языки,
зависимые от реализации, которые претендуют на универсальное
применение (например, Delphi Object Pascal, C#, Java ).
4)
До него был еще Algol 58, но лишь Algol 60 был утвержден в качестве
стандарта и получил широкое распространение. Его часто называют в
литературе просто Алгол .
5)
Прежде всего, физиков и американцев; европейцы, не являвшиеся
физиками, приняли его хорошо.
6)
Такова цена, которую пришлось заплатить за полную формальную
точность описания.
7)
Одно из центральных понятий программирования — это призрак:
то, что нужно для понимания программы, но в программу не входит.
Pascal и Алгол 68 позволили многим призракам стать реальными
программными сущностями.
8)
Безусловно, это тормозит развитие машинных архитектур.
9)
Это утверждение не противоречит долголетию С. Как уже
отмечалось, данный язык сегодня фактически навязывает архитектуру
машин, которая не противоречит его эффективной реализации.
Например, использование С в качестве базового языка для Эльбруса
явно ограничивало бы доступ ко многим развитым машинным
возможностям.
10)
В качестве анекдота заметим, что система описаний С++ настолько
мощна, что на стадии трансляции в принципе можно вычислить любую
программу, например, выдавая результат в качестве сообщения об
ошибке.
11)
Про новые условия данного проекта говорят обычно с неохотой или
же вовсе замалчивают их. К примеру, в книге " Java -технология" успех
старой идеи в новом проекте объясняется тем, что в прежние времена
эту идею изучали в университетах, тогда как сегодня за нее взялись
промышленники.
12)
В этой связи уместно следующее замечание. Если бы книга [24
] не
была бы сегодня библиографической редкостью, то ее главу 2 "Рабочая
программа" можно было бы рекомендовать в качестве пособия для тех,
кто желает изучить устройство Java -машины. После прочтения
понимание Java -машины окажется более глубоким.
Стили и методы программированияНепейвода Н.Н.
47

Синтаксис, семантика и прагматика
Как определять язык программирования? Язык как текст (синтаксис).
Язык как исполнимый текст (семантика). Конкретизация языка для
данной обстановки. Какая часть синтаксиса нужна для семантики?
Данная лекция вводит в проблему точного определения языка
программирования
1)
лишь настолько, насколько это необходимо для
понимания последующего анализа языков и стилей. Эта проблема
многогранна, и более подробное ее рассмотрение дается в другом курсе.
Различные стороны определения языка
Для создания, проверки и преобразования программ, построения
систем программирования, а также для многих других нужд нам
необходимо если не определение, то хотя бы описание
алгоритмического языка. При этом требуются точные описания как
текстов, так и их интерпретации. Рассмотрим существующие варианты.
1. Сама программа-транслятор считается описанием языка. Тут сразу
точно описаны и тексты (правильная программа — та, на которой
транслятор не выдает ошибки), и их интерпретация
(интерпретация программы — то, как исполняется ее текст после
перевода транслятором).
Именно так пытались поступать на заре программирования, когда,
скажем, легендарный язык FORTRAN создавался одновременно с
первым транслятором с данного языка.
2. Определением языка считается формальная лингвистическая
система (грамматика). Впервые этот подход был последовательно
применен в Алголе. Встречавшиеся вам при изучении языков
синтаксические диаграммы являются непосредственными
потомками того, что было сделано в Алголе.
3. Определением языка считается соответствие между структурными
единицами текста и правилами интерпретации. Этот вариант был
полностью реализован при определении языка Алгол 68.
Стили и методы программированияНепейвода Н.Н.
48

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

программу в ходе ее исполнения.
Прагматика алгоритмического языка — то, что связывает программу с ее
конкретной реализацией. При этом, в частности, происходит
следующее.
1. Все определения становятся явными (изгоняются такие понятия,
как "не определено", "определяется реализацией" и т. п.)
2)
.
2. Появляются дополнительные конструкции, описатели и др.,
обусловленные реализацией. Они обязательно учитывают:
особенности вычислительной машины и среды
вычислений;
особенности принятой схемы реализации языка;
обеспечение эффективности вычислений;
ориентацию на специфику пользователей.
Прагматика иногда предписывается стандартом языка, иногда нет. Это
зависит от того, для каких целей предназначены язык и его реализация.
Описание языка требует точного задания синтаксиса и семантики. На
практике, однако, чем точнее и чем лучше для построения транслятора
описан язык, тем, как правило, такое описание более громоздко и менее
понятно для обычного человека, и поэтому точные описания
существуют не для всех реальных языков программирования. Даже если
они имеются, то в виде стандартов, к которым обращаются лишь в
крайних случаях.
Синтаксис
Синтаксис — самая простая и самая разработанная часть описания
алгоритмического языка.
Грамматика определяется системой синтаксических правил (чаще всего
в описаниях языков называемых просто правилами ). На уровне
грамматики определяются понятия, последовательное раскрытие
которых, называемое выводом, в конце концов дает их представление в
виде последовательностей символов. Символы называются также
терминальными понятиями, а все остальные понятия
Стили и методы программированияНепейвода Н.Н.
50
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
