Copyright (C) А.Гавва V-0.4w май 2004

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

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

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

2.1 Объектно-ориентированное программирование

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

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

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

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

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

2.2 Сущность абстрактного типа данных

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

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

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

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

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

2.2.1 Структура абстрактного типа данных

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

2.2.2 Средства Ады для работы с абстрактными типами данных

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

  1. Подтипы - позволяют описывать классы численных и перичислимых значений, и назначать им ограничения диапазонов значений, что позволяет компилятору осуществлять строгий контроль над корректностью используемых значений.
  2. Инициализация полей записи - позволяет описывать тип записи так, что каждое индивидуальное поле записи, в каждой переменной этого типа, будет предварительно инициализировано предопределенным значением.
  3. Пакеты - являются идеальным средством группирования совместно используемых ресурсов (типы, процедуры, функции, важные константы...) и предоставления этих ресурсов клиентским программам. При этом осуществляется строгий контроль над контрактной моделью пакета: все что обещано в спецификации пакета должно быть обеспечено в теле пакета, а клиентская программа должна корректно использовать ресурсы предоставляемые пакетом (например, вызывать процедуры только с корректными параметрами).
  4. Приватные типы - позволяют разрабатывать пакеты, которые предоставляют клиентским программам новый тип данных таким образом, чтобы клиентская программа не имела возможности выполнить непреднамеренное изменение значений путем использования приватной информации о внутреннем представлении данных приватного типа, ограничивая тем самым возможность использования внутреннего представления приватного типа данных только внутри тела пакета.
  5. Совмещение знаков операций - позволяет определять новые арифметические знаки операций и знаки операций сравнения для вновь определяемых типов данных, и использовать их также как и предопределенные знаки операций.
  6. Определяемые пользователем исключения - позволяют разработчику пакета предусматривать исключения для клиентской программы, которые будут сигнализировать клиентской программе о том, что внутри пакета выполнены какие-либо неуместные действия. В свою очередь, разработчик клиентской программы может предусмотреть обработку исключений, которые могут возникнуть внутри используемого клиентской программой пакета.
  7. Атрибуты - позволяют создавать подпрограммы для манипуляции структурами данных без наличия всех деталей организации данных (например, атрибуты 'First и 'Last для массивов).
  8. Настраиваемые модули - позволяют создавать подпрограммы и пакеты, которые имеют более общий характер. Это подразумевает, что в процессе написания настраиваемого модуля отсутствует информация о фактически обрабатываемом типе данных. Тип данных может быть указан как параметр настройки позже, в процессе конкретизации настраиваемого модуля.

2.3 Пакеты в языке Ада

2.3.1 Пакеты как средство абстракции данных

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

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

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

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

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

Первый из этих механизмов представляет собой важное новшество, внесенное языками, подобными языку Ада. Использование его настоятельно рекомендуется. Второй из этих механизмов использовать нежелательно. Его применение ведет к появлению трудночитаемых и трудноотлаживаемых программ и является "вредным наследием" блочно-структурированных языков, подобных Алголу-60.

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

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

2.3.2 Сравнение пакетов и классов

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

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

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


Copyright (C) А.Гавва V-0.4w май 2004