к оглавлению   к 3GL   к визуальным средам - 4GL   к архитектуре DB-интерфейсов   к технологии программирования

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

Языковые абстракции

3.1. Отступление "об абстрагировании"

Сотри случайные черты, и ты увидишь - мир прекрасен.
Александр Блок

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

Абстрагирование в информатике имеет некоторые особенности, отмеченные Питером Деннингом (Peter Denning) в следующем определении. Абстрагирование в информатике - моделирование возможных реализаций. Модели подавляют детали, но оставляют существенные особенности. Отличие от математики еще и в том, что мы рассматриваем абстракции одновременно как по отношению к решаемой проблеме, так и по отношению к физической машине (второе в математических абстракциях отсутствует). Мы рассмотрим три типа абстракций в языках программирования [Appleby 1991].

Абстрагирование особенно актуально для двух групп языков, которые мы определили как языки моделирования и программирования.

3.2. Абстракция данных

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

3.2.1. Данные и типы данных

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

Исторически можно проследить несколько этапов в становлении типов данных в языках программирования.

3.2.2. Эволюция определения типа данных

Современное определение типа данных звучит так. Тип данных - это множество значений, определяемых посредством множества операций.

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

Об основном вопросе в области типов данных

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

3.2.3. Абстрактные типы данных

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

Развернутое определение абстрактного типа данных включает в себя следующие части:

Обоснование применимости концепции абстрактных типов данных в практике программирования было сделано Хоаром (С.A.R. Hoare). Некоторая программа, работающая с данными типа т и содержащая последовательность операторов, реализующих операции с этим типом, может быть преобразована в функционально-эквивалентную программу. В результирующей программе каждая операция с типом т может быть описана в виде функции, а все явно запрограммированные действия с этим типом могут быть заменены вызовами соответствующих функций.

3.2.4. Разновидности полиморфизма

Все языки могут быть разделены на две группы.

Полиморфные типы - типы, чьи операции применимы к значениям более чем одного типа. Полиморфные функции - функции, чьи операции (параметры) могут иметь значения более одного типа.

Выделяют два класса и четыре основных подкласса полиморфизма [Cardelli, Wegner 1985].

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

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

3 + 4

3.0 + 4

3 + 4.0

3.0 + 4.0

Неуниверсальный полиморфизм оператора сложения + может быть представлен тремя случаями.

О перегрузке
Бьерн Страуструп (Bjarne Stroustrup) в статье "Generalizing Overloading for С++ 2000" (http://www.research.att.com/-bs/papers.html), датируемой 1 апреля 1998 г., предлагает развивать идеи перегрузки в языке C++. Например, предлагается перегружать не только пробелы, но и пропущенные пробелы.

3.2.5. Статический и динамический контроль типов

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

Существуют два типа контроля.

3.2.6. Статически и динамически типизируемые языки программирования

Языки программирования могут быть статически и динамически типизируемыми. -. ,.|

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

Одним из наиболее интересных динамически типизируемых языков программирования является язык "Автокод Эльбрус" [Сафонов 1989]. При определении переменной целочисленного типа данных отводится лишь области памяти необходимого формата. Например, описание ф64 а указывает на необходимость отведения для переменной а 64-х битов, в которых далее может быть размещено целое число. Динамическая типизация может быть эффективно поддержана аппаратной реализацией (например, архитектура Эльбрус для языка "Автокод Эльбрус").

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

3.3. Абстракция управления

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

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

Примерно так выглядело историческое становление концепции структурного программирования:

Чем еще интересны структурированные программы? В 1965 году академик Глушков обратил внимание на то, что структурированные программы можно рассматривать как формулы в некоторой алгебре. Зная правила преобразования выражений в такой алгебре, можно осуществлять глубокие формальные (и, следовательно, автоматизированные) преобразования программ.

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

3.3.2. Визуальное структурное программирование

Визуальное структурное программирование также базируется на классической работе [Дейкстра 1975]. Дейкстра предлагает ограничить топологию блок-схем, запретив проведение стрелок из любого блока в любой другой блок. Идея визуального структурного программирования - перейти от одномерного линейного представления программы к двумерному, графическому. Языки такого программирования - это языки моделирования. На сегодняшний день наиболее известны три из них.

Графоэлементы языка ДРАКОН называются иконами, которые могут объединяться в составные иконы - макроиконы. Шампур-блок - часть ДРАКОН-схемы, имеющая один вход сверху и один выход снизу, элементы, расположенные на одной вертикали. Терминатор - часть ДРАКОН-схемы, имеющая либо один выход снизу и не имеющая входа, либо один вход сверху и не имеющая выхода. Ветки - смысловые блоки, куски алгоритма, представляющие составной оператор языка ДРАКОН. С помощью веток удобно формализовать смысловое разбиение проблемы, программы или процесса на части и дать частям удобные смысловые названия. На рис. 4.10 приводится пример ДРАКОН-схемы с двумя ветками.

Обратим внимание на то, что долгое время в Америке отвергалась идея визуального программирования, и основной упор там делался на создание универсального языка программирования.

3.3.3. Оператор перехода

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

С точки зрения языка высокого уровня выделяют:

if (условие) then действие;

switch дискриминант case значение действие case ...;

Укажем некоторые особенности условного оператора в разных языках программирования:

3.3.4. Оператор итерации

Под итерацией будем понимать обращение ко всем элементам агрегата в определенном порядке, причем каждый элемент посещается единожды. Самый простейший пример итератора - оператор for. Многие языки поддерживают также операторы while ... do ... И repeat . . . until.

В некоторых языках программирования итератор традиционно представляется в виде процедуры. Например, так на языке CLU может быть написано суммирование всех элементов множества s с помощью итератора elements (s) (листинг 4.1).

Листинг 4.1. Пример использования итератора

setsum = proc(s:intset)returns(int)signals(NumOverFlow)

sum: int := 0

for i: int in intset$elements(s) do

sum := sum + i

end

return(sum)

end setsum

Итераторы могут быть положены в основу декларативного программирования. Так можно на декларативном языке указать множество жителей города Старый Петергоф:

which (х: х живет в Старом Петергофе)

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

3.3.5. Оператор исключения

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

Одно из наиболее подробных исследований принципов реализации исключений было выполнено Страуструпом [Страуструп 2000]. В частности, им обсуждались две стратегии обработки исключений в языке C++.

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

Обратим внимание на то, что многие широко распространенные языки программирования (например, Pascal) не имеют механизма обработки прерываний.

Понятие обработки событий впервые появилось в языке PL/I. Система прерываний (так это называлось в PL/I) была предназначена для проверки и обработки различных условий, которые могут возникнуть в ходе выполнения программы. Основные категории условий в языке PL/I следующие:

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

(subscriptrange): begin

...

end;

Язык "Автокод Эльбрус" имеет конструкцию, называемую структурное предложение. Это наиболее развитый на сегодняшний день механизм обработки событий, который образно можно назвать "goto с человеческим лицом". Основные ситуации в языке "Автокод Эльбрус" таковы:

Пример структурного предложения языка "Автокод Эльбрус" выглядит так:

до c1, с2

% закрытое предложение

...

при

c1: <обработчик 1>,

с2: <обработчик 2>

всесит

Структурный переход по ситуации c1 в закрытом предложении может быть выполнен, например, следующим образом: c1!.

3.3.6. Зависимости по управлению и по данным

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

Пример зависимости по управлению:

if ( c1)

{ s1; } /*исполнение этого оператора зависит от c1 */

s2;

Существуют три разновидности зависимости по данным.

S1: а:=3;

S2: b:=a;

S3: с:=а+3;

S1: а:=b+3;

S2: b:=47;

S1: a:=x+2;

S2: b:=a-3;

S3: а:=с-45;

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

3.4. Абстракция модульности

3.4.1. Модульное программирование

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

3.4.2. Определения модуля и его примеры

Приведем несколько дополнительных определений модуля.

Функциональная спецификация модуля должна включать:

Существуют три основные разновидности модулей, приведенные ниже.

3.4.3. Характеристики модульности

Первый набор характеристик предложен Хольтом [Holt 1975]. Это два общих требования.

Второй набор предложен Майерсом [Майерс 1980]. Он состоит из следующих конструктивных характеристик:

Размер модуля

Вот несколько общих советов по наилучшему размеру модуля.

О необходимости именно 7 (+/-2) конструкций
Это число берется на основе представлений психологов о среднем оперативном буфере памяти человека. Символьные образы в человеческом мозгу объединяются в "чанки" - наборы фактов и связей между ними, запоминаемые и извлекаемые как единое целое. В каждый момент времени человек может обрабатывать не более 7 чанков.

Связность (прочность) модуля

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

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

О средствах задания информационной связности
Обратим внимание на то, что средства для задания информационно прочных модулей отсутствовали в ранних языках программирования (например, FORTRAN и даже в оригинальной версии языка Pascal). И только позже, в языке программирования Ada, появился пакет- средство задания информационно прочного модуля.

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

Сцепление модулей

Сцепление (coupling) - мера относительной независимости модуля от других модулей. Независимые модули могут быть модифицированы без переделки других модулей. Чем слабее сцепление модуля, тем лучше. Рассмотрим различные типы сцепления.

Оставшиеся три типа сцепления не рекомендуется использовать.

Рутинность модуля

Рутинность - это независимость модуля от предыдущих обращений к нему (от предыстории). Будем называть модуль рутинным, если результат его работы зависит только от количества переданных параметров (а не от количества обращений).

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

к оглавлению   к 3GL   к визуальным средам - 4GL   к архитектуре DB-интерфейсов   к технологии программирования

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

НОВОСТИ ФОРУМА

Форум Рыцари теории эфира


Рыцари теории эфира
 10.11.2021 - 12:37: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
10.11.2021 - 12:36: СОВЕСТЬ - Conscience -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
10.11.2021 - 12:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от д.м.н. Александра Алексеевича Редько - Карим_Хайдаров.
10.11.2021 - 12:35: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ПРАВОСУДИЯ.НЕТ - Карим_Хайдаров.
10.11.2021 - 12:34: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вадима Глогера, США - Карим_Хайдаров.
10.11.2021 - 09:18: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> Волновая генетика Петра Гаряева, 5G-контроль и управление - Карим_Хайдаров.
10.11.2021 - 09:18: ЭКОЛОГИЯ - Ecology -> ЭКОЛОГИЯ ДЛЯ ВСЕХ - Карим_Хайдаров.
10.11.2021 - 09:16: ЭКОЛОГИЯ - Ecology -> ПРОБЛЕМЫ МЕДИЦИНЫ - Карим_Хайдаров.
10.11.2021 - 09:15: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Екатерины Коваленко - Карим_Хайдаров.
10.11.2021 - 09:13: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вильгельма Варкентина - Карим_Хайдаров.
Bourabai Research - Технологии XXI века Bourabai Research Institution