Обмен с внешней средой (ввод-вывод) обслуживается в Аде предопределенными библиотечными пакетами. Имеются средства обмена значениями не только предопределенных типов (как в Паскале), но и типов, определяемых программистом.
Наконец, имеются средства статической параметризации модулей (действующие до начала исполнения программы, в период компиляции) - аппарат РОДОВЫХ модулей. Параметры таких модулей (родовые параметры) в отличие от динамических параметров подпрограмм и процедур могут быть не только объектами данных некоторого типа, но и такими объектами, как типы и подпрограммы (которые в Аде не считаются объектами данных). Так что общие модули, рассчитанные на применение ко всем типам данных определенной категории, в Аде следует оформлять как родовые.
На этом закончим краткий обзор языка.
2.4. Пошаговая детализация средствами Ады
Рассмотрим следующую задачу.
Содержательная постановка. Необходимо предоставить пользователю комплекс услуг, позволяющих ему моделировать сеть связи. Пользователь должен иметь возможность изменять сеть (добавлять и убирать узлы и линии связи), а также получать информацию о текущем состоянии сети.
Требования к реализации. Во-первых, должна быть гарантирована целостность сети при любых возможных действиях пользователя. Другими словами, ни при каких условиях не должны возникать линии связи, не ведущие ни в один узел. Во-вторых, предполагается развивать возможности моделирования (например, отражать стоимость связей). Важно, чтобы при этом у пользователя не возникала необходимость изменять готовые программы.
Оба этих требования можно удовлетворить, если строго регламентировать доступ пользователя к представлению сети в памяти компьютера. Тогда заботу о целостности сети можно возложить на средства доступа к ней, а при развитии комплекса услуг можно изменять представление сети, сохраняя все старые средства доступа (и, следовательно, ранее работавшие программы пользователя).
Первый шаг детализации. Уточним постановку задачи в терминах языка Ада. Так как речь идет не об алгоритме, а о предоставлении пользователю комплекса услуг, в Ада-терминах естественно отобразить этот комплекс на совокупность "логически связанных" объектов, в данном случае - связанных по меньшей мере совместным использованием. Другими словами, первое наше решение - создавать ПАКЕТ, а не подпрограмму или задачу. Вспоминая, что разделение спецификации и тела пакета позволит скрыть от пользователей пакета детали реализации (в частности, представление сети, в полном соответствии с требованиями), получаем еще одно подтверждение, что решение правильное.
Итак, создаем ПАКЕТ. Нужно придумать ему название, выражающее назначение предоставляемого комплекса услуг. Попробуем "сеть". Нехорошо. По-видимому, так лучше называть тот объект, который будет моделироваться, и чье представление нужно скрыть в теле нашего пакета. Попробуем "моделирование сети связи". Лучше, но слишком конкретно. Хотя в постановке задачи и требованиях речь идет именно о моделировании сети связи, однако специфика связи (кроме самой сети) ни в чем не отражена (нет и речи о пропускной способности каналов, классификации сообщений и т. п.), да и специфика моделирования не затронута (никаких моделей отправителей, получателей и т. п.). Скорее мы собираемся предоставить лишь комплекс услуг по управлению сетью. Так и назовем пакет:
"управление_сетью".
Точное название настраивает на то, чтобы в пакете не было лишнего, а пользователю помогает применять наш комплекс и в других областях.
Второй шаг детализации. Теперь нужно написать спецификацию пакета, объявив все объекты, с которыми сможет работать пользователь:
0. with параметры_сети; use параметры_сети;
1. package управление_сетью is
2. type узел is new INTEGER range 1..макс_узлов;
3. type число_связей is new INTEGER range 0..макс_связей;
4. type индекс_узла is new INTEGER range 1..макс_связей;
5. type перечень_связей is array (индекс_узла) of узел;
6. type связи is
7. record
8. число : число_связей := 0;
9. узлы : перечень_связей;
10. end record ;
11.-- операции над сетью
12. procedure вставить (X : in узел);
13. procedure удалить (X : in узел);
14. procedure связать (X, Y : in узел);
15.-- сведения о текущем состоянии сети
16. function узел_есть (X : узел) return boolean;
17. function все_связи (X : узел) return связи;
18. end управление_сетью;
Текст спецификации пакета с названием "управление_сетью" при первоначальном знакомстве может показаться непонятным. Во всяком случае не верится, что он получен одним шагом детализации. Действительно, шаг зависит как от привычки проектировщика, так и от свойств языка. Ведь в общем случае далеко не каждый мелкий шаг поддерживается подходящим законченным языковым конструктом. Например, в Аде шаги нельзя дробить сколь угодно мелко хотя бы потому, что действует правило последовательного определения: при очередном определении можно использовать только предопределенные, внешние или ранее объявленные имена.
Но при пошаговой детализации нельзя заранее объявить те имена, которые понадобятся - они попросту неизвестны. Когда проектируют совокупность модулей, это не помеха (порядок модулей несуществен). А вот внутри модулей правило последовательного определения мешает пошаговой детализации [особенно внутри пакетов; почему?]. Приходится либо применять средства, выходящие за рамки Ады (например, псевдокод), либо записывать пакет "с конца к началу" - этот порядок с учетом правила последовательного определения лучше отражает последовательность появления имен при пошаговой детализации.
С точки зрения принципа технологичности. любые несоответствия языка потребностям пошаговой детализации служат источником "точек роста", намечают направление развития либо самого языка, либо других связанных с ним технологических инструментов. Для Ады, в частности, разрабатываются специальные средства поддержки пошагового конструирования программ.
Упражнение. Укажите внешний эффект (исходные данные и результаты) хотя бы одного из таких средств.
Подсказка. Редактор, располагающий фрагменты Ада-программы в порядке, соответствующем правилу последовательного определения.
Упражнение (повышенной сложности). Разработайте проект хотя бы одного такого средства; проект комплекса таких средств.
Итак, проявим более мелкие шаги проектирования нашего пакета.
Шаг 2.1 (строка 17). Объявляем функцию с названием "все_связи", формальным параметром с названием "X" (значениям этого параметра приписан тип с названием "узел") и результатом, которому приписан тип с названием "связи".
Ниже будем писать короче: функцию "все_связи" с параметром "X" типа "узел" и результатом типа "связи.
Эта функция дает возможность узнавать о текущем состоянии сети (точнее, о связях одного узла). Обратите внимание, пока совершенно неясно, что такое "узел" и "связи". Это лишь названия, отражающие роль в создаваемом комплексе услуг тех объектов, которые еще предстоит воплотить в программе.
Шаг 2.2 (строка 16). Нехорошо запрашивать связи узла, не зная, имеется ли он в сети. Поэтому (продолжая предоставлять средства узнавать о состоянии сети) объявляем функцию узел_есть с параметром "X" типа узел и результатом логического типа (BOOLEAN).
Замечание. Обратите внимание, мы записываем только формальные СПЕЦИФИКАЦИИ (заголовки) функций. Содержащихся в них сведений достаточно, чтобы можно было (столь же формально) написать вызов такой функции. Но, во-первых, рано или поздно придется написать ТЕЛО функции (сделаем это в ТЕЛЕ пакета). Во-вторых, нужно как-то сообщить пользователю, что же делает объявляемая функция.
Например, из объявления в строке 16 пользователь поймет, что, задав функции узел_есть аргумент типа узел, он получит в качестве результата истину или ложь. Не откуда ему узнать, что истина соответствует случаю, когда узел с указанным именем есть в сети, а ложь - когда его нет. Название функции лишь намекает на такое истолкование. Конечно, названия должны быть мнемоничными и помогать запоминать смысл программных объектов, но они не могут заменить точных сведений.
Ада не предоставляет специальных средств для полного и точного описания внешнего эффекта модуля. Ведь адовские спецификации рассчитаны прежде всего на исполнителя, на компьютер, а отнюдь не на пользователя. Поэтому, как и в случае с другими ЯП, проектирование Ада-модуля следует сопровождать проектированием точного описания его внешнего эффекта (применяя при необходимости средства, выходящие за рамки ЯП). Некоторые экспериментальные языки предоставляют встроенные средства соответствующего назначения.
Часто бывает необходимо параллельно создавать и описание внешнего эффекта, специально ориентированное на пользователей. Эта так называемая пользовательская документация принципиально отличается от описаний, рассчитанных на автомат-транслятор (именно таковы описания на ЯП) или человека-реализатора, по структуре документов, стилю изложения, выделяемым свойствам объектов и т. п.
С точки зрения пользовательской документации на программное изделие, ЯП всегда выступает в роли инструмента реализации. Он тем лучше, чем проще объяснить пользователю назначение выделенных программных компонент и чем ими удобнее и дешевле пользоваться. Назовем соответствующий критерий качества языка критерием выделимости.
По выделимости Ада превосходит, например, Алгол-60 или Бейсик, так как позволяет адекватно оформлять не только компоненты-функции, но и компоненты-данные, и компоненты-задачи, и компоненты более "тонкого" назначения. Другими словами, Ада выигрывает в выделимости потому, что предоставляет более развитые средства абстракции и конкретизации.
Упражнение. При чем здесь абстракция-конкретизация?
Шаг 2.3 (строки 12-14). Предоставляя средства для изменения сети, определяем три процедуры: вставить, удалить и связать (параметры у них типа узел).
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |


