Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AlgStr / Лекции.doc
Скачиваний:
44
Добавлен:
23.03.2015
Размер:
741.89 Кб
Скачать

14101954

Что оно означает? Каков его формат? Возможно это просто набор отдельных цифр: один, четыре, один, ноль, один, девять, пять, четыре. Возможно это просто целое положительное число: четырнадцать миллионов сто одна тысяча девятьсот пятьдесят четыре. Еще один вариант – это дата: четырнадцатое октября тысяча девятьсот пятьдесят четвертого года. Как мы видим из рассмотренного нами примера все зависит от того как мы интерпретируем предоставленные нам данные или изображение информации. Из этого можно сделать вывод, что формат и тип данных по своей сути есть одно и то же. Из за показанной здесь неоднозначности следует что к каждому источнику данных требуется свой интерпретатор данных: некая сущность, которая знает правильный формат данных поступающих из источника. Без него мы не сможем получить из данных информацию и наоборот.

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

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

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

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

Контроль типов должен обеспечит надежность программ.

Тип данных определяется по существу двумя свойствами:

  • поведением объекта, рассматриваемого типа;

  • структурным описанием,  определяет представление объектов этого типа;

  • (не обязательно) множество объектов рассматриваемого типа;

Под типом объекта понимается:

  • само множество объектов;

  • существенные свойства, т.е. представление объектов этого множества;

  • набор операций обеспечивающий доступ к объектам и позволяющий использовать их свойства;

Эта характеристика особенно существенна в таких приложениях как базы данных, где время существования объекта представляет непосредственный интерес.

В связи с этим можно предложить такое определение:

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

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

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

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

1) напоминает, что представление типа данных (в период компиляции), извлеченное из спецификации этого типа, имеет решающее значение для эффективности (в период компиляции) контроля типов;

2) дает удобную основу для классификации механизмов типов данных в ЯВУ.

<Тип данных> ::= <множество допустимых значений, набор операций, внутреннее представление>

Тип данных определяется:

  1. Поведением объектов рассматриваемого типа;

  2. Представлением (форматом) объектов этого типа

  3. Множеством объектов этого типа

Тип данных это процедура периода компиляции. Если тип данных является встроенным в язык высокого уровня, то он предоставляет там следующие средства:

  1. Объявить переменную этого типа

  2. Объявление констант данного типа

  3. Сравнение значений

  4. Присваивание и определение значений

  5. Определение компонент типа (только для сложных типов)

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

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

  2. Каждое значение принадлежит одному и только одному типу(данное правило не нарушается в языке Паскаль во многом благодаря неявному приведению типов).

  3. Тип константы, переменной или выражения можно вывести либо из контекста либо из вида самого выражения не обращаясь к значениям, вычислимым во время работы программы, что обеспечивает возможность статического контроля типов.

  4. Для каждой операции существует тип ее операндов и результата.

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

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

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

К простым типам относятся порядковые и вещественные типы.

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

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

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

Классификация средств определения данных в Я.В.У.

1) Средства структурирования данных (ФОРТРАН, АЛГОЛ 60, КОБОЛ, ПЛ/I).

Каждый из этих языков содержит множество встроенных типов и обеспечивает средства структурирования составных объектов. Типичный набор встроенных типов включает:

  • cкалярные типы (integer, real, boolean, char, …)

  • структурные (array, record, union, pointer)

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

Ключевой вопрос - когда два объекта имеют олин и тот же тип - может оказаться весьма сложным, особенно при наличии в языке записей. Например, в языке ПЛ/I используется сложная система правил совместимости структур, а в КОБОЛе единственным требованиеми при передаче параметра является необходимость того, чтобы фактический и формальный параметры занимали область памяти одной и той же длины.

2) Средства определения типа (АЛГОЛ 68, ПАСКАЛЬ).

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

Type

имя типа = <описание типа>

Это дает два преимущества:

- удобное сокращение;

- можно создавать различные типы с одним и тем же представлением (для контроля совместимости).

Недостатки:

- поведение не очевидно

3) Абстрактные типы данных (АТД) (CLU, Modula, Ada).

АТД – это, по существу, определение нового понятия в виде класса (одного или более) объектов с некоторыми свойствами и операциями.

Эта идея родилась у Morris, B. Liskov.

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

4) Средства ООП.

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

Элементы ООП:

  • объекты;

  • каждый объект является реализацией некоторого класса;

  • классы организованы иерархически;

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

I-ое поколение: АЛГОЛ 60, ФОРТРАH.

Имели простейшие средства структурирования (массивы).

II-ое поколение: ПАСКАЛЬ, АЛГОЛ 68, ПЛ/I.

Имеют более мощные средства структурирования данных, появились средства

определения новых типов данных, но еще не имели средств А.Т.Д.

III-е поколение: СИМУЛА 67 (прародитель всех этих языков), CLU, ALPHARD,

МОДУЛА, АДА.

Имеют средства А.Т.Д. Но не поддерживают наследование.

IV-е поколение: появились ООП языки (С++, Object Pascal).

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

ВСТРОЕННЫЕ ТИПЫ ДАННЫХ

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

1) описание переменной;

2) взятие значения и присваивание;

3) сравнение значений;

4) обозначение констант;

5) выбор компонент (селектор).

Рассмотрим пример организации типов данных на примере языка ПАСКАЛЬ. По словам автора языка ПАСКАЛЬ Н.Вирта организация типов данных в ПАСКАЛе основывается на теории структурной организации данных Хоара. Ее отличительными особенностями являются :

1) Тип данных определяет класс значений, которые могут принимать переменные или выражения;

2) Каждое значение принадлежит одному и только одному типу;

3) Тип значения константы, переменной или выражения можно вывести либо из контекста, либо из вида самого операнда, не обращаясь к значениям, вычисленным во время работы программы;

4) Каждой переменной соответствует некоторый фиксированный тип результата;

5) Для каждого типа свойства значений и элементарных операций над значениями задаются с помощью аксиом;

6) При работе с языком ВУ значение типа позволяет обнаруживать в программе бессмысленные конструкции (контроль типов) и решать вопрос о методе предсавления данных и преобразованиях их в вычислительной машине

Средства структурирования данных

1. Массивы.

Описание массива состоит из нескольких частей:

- описание его элементов;

- описание его границ.

В общем случае определение границ бывает трех видов:

- статическое (границы фиксируются в период компиляции);

- динамическое (границы фиксируются в момент входа в область локализации);

- подвижное (допускается изменение границ в период выполнения).

Динамические массивы (АЛГОЛ 60) создают проблемы с проверкой тождественности типа.

Требуется хранить в период выполнения размерности в информационном векторе и это необходимо динамически проверять (издержки) или считать, что массивы однотипны, если у них один и тот же тип элементов.

Подвижные массивы (АЛГОЛ 68, СHОБОЛ). Те же проблемы, что и с динамическими массивами. Они главным образом влияют на принципы языка, касающиеся распределения памяти, поскольку требуется какого-то рода управление свободной памятью в период выполнения.

2. Записи.

Запись определяется как последовательность компонент, каждая из которых состоит

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

1) Какова роль имен полей компонент.

Hапример, имеют ли один и тот же тип следующие записи:

record (A: integer; B: boolean);

record (B: booltan; A: integer);

record (C: integer; D: boolean);

3. Типы, задаваемые перечислением.

Этот тип позволяет обозначать данные с помощью символических имен, а не их

представлений в виде небольших целых чисел.

Здесь существуют такие вопросы:

Законны ли описания

var

S1 : (валет, дама, король);

S2 : (король, президент, канцлер);

или два короля должны иметь разные имена?

Речь идет о том предпочесть ли удобство пользователя в обмен на сложность языка или реализации.

Здесь возможны несколько реализаций:

1) Тип символического имени (литерала) зависит от контекста.

Hапример

S1 := король;

зависит от типа S1.

2) Проверять при присваивании и когда нужно осуществлять приведение

(из-за различного представления).

Другой вопрос: должны ли они быть упорядоченными или нет? Обычно ответ - да.

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

4. Отрезки типов.

Это обозначение некоторого типа с упорядоченным множеством значений вместе

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

Вопрос: обозначают ли разные спецификации один и тот же тип?

Самое простое решение: считать все отрезки некоторого типа, принадлежащими

одному и тому же типу.

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

Иногда это можно сделать уже при компиляции:

var

I : 1..100;

J : 10..20; ... I := J;

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

5. Объединения (Union).

Эти средства были ииедены из желания использовать одну и ту же область памяти

для объектов различных типов:

ФОРТРАH : EQUIVALENCE

КОБОЛ : REDEFINES и RENAMES

ПЛ/I : DEFINED

В ранних языках такая возможность не рассматривалась как относящаяся к определениям

типов.

Hо даже в новых языках, где объединение появилось в качестве средства определения типа, оно рассматривалось как "свободное объединение", т.е. нет никакой защиты от того, что некоторый объект определяется как объект одного типа, а затем используется (через имя объекта, принадлежащего объединению) так, как будто он объект другого типа.

Hесколько языков пытаются обеспечить "безопасную" форму объединения ("размеченное" объединение).

Hапример, в языке ПАСКАЛЬ - запись с вариантами. Объект типа объединение в каждый момент времени представляет собой (содержит) в точности одну из этих компонент. Указатель поля объекта обычно называют "ярлычком" (tag). Он непосредственно доступен программисту и указывает какая из альтернатив имеет место в данный момент.

Основной вопрс здесь: стоит ли жертвовать эффективностью выполнения ради надежности (безопасности) программы или наоборот.

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

- каковы роли имен полей, спецификаций типов компонент и порядка компонент

в определении типа объединение?

Hапример, рассмотрим описание

var

U: Union (A: integer; B: ^integer);

6. Указатели.

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

Hапример, в языке ПЛ/I нет ничего, что бы помешало программисту установить указатель на объект одного типа, а затем интерпретировать указанный им объект так, как будто он имеет другой тип.

Hо в этом случае упрощается проблема равенства типов. В противном случае необходим строгий контроль типов, но в этом случае проблема тождества типов становится сложнее.

Средства определения новых типов.

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

Hапример

type T1 = array [1..100] of real;

T2 = array [1..100] of real;

var V1: T1; V2: T2;

V3: array [1..100] of real;

Что можно сказать о V1 и V2?

о V1 и V3?

Самое простое решение принято в АЛГОЛе 68: Там переменные считаются эквивалентными, если они имеют одну и ту же структуру (структурная эквивалентность).

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

Лекция 5. Абстракция и декомпозиция и их взаимодействие при разработке программ

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

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

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

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

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

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

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

При декомпозиции задачи мы разбиваем ее на ряд подзадач так, что

  1. каждая подзадача имеет один и тот же уровень рас­смотрения;

  2. каждая задача может быть решена независимо;

  3. полученные решения могут быть объединены вместе, позволяя решить исходную проблему.

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

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

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

Соседние файлы в папке AlgStr