Документирование процесса разработки
ПО
А.Г.Пискунов
2 сентября 2025 г.
agp1.fmsd 1.02.10
2
ПРЕДИСЛОВИЕ
В отчете обсуждаются использование системы документирования
исходных текстов Doxygen и системы компьютерной верстки LaTex
в процессе разработки ПО. Уделяется внимание таким языкам формальных спецификаций как RSL и Z, разработки спецификаций отдельных модулей, разработки набора тестов, проверки спецификаций при помощи утилиты RSLTC. При этом методы формальной
разработки (см. например, [55, 2, 60]) обсуждаются мимоходом. Есть
прямо таки уверенность, что читатель никогда не попадет в группу разработчиков, где будут использоваться формальные методы.
Поэтому, цель курса – освоение LaTex-а и языков формальных спецификаций в объеме, достаточном для индивидуального использования, то есть, для точного описания разрабатываемого ПО и хранения этого описания непосредственно в тексте программ. Применение
языка RSL к разработке ПО (ну, кроме [33]) можно посмотреть в работах [40, 74, 68]; применение Z – кроме [17], в отчетах [83, 81].
В настоящем документе используется информация из курса программирования на языке C# (см. [76, 63, 64]), В курсе по модульному тестированию (см. [82]) рассматриваются вопросы возможной
интерпретации спецификаций языка RSL средствами языка реализации. в данном случае языком реализации является язык C#. !!wrong
command: !!Последняя версия документа расположена по адресу [80].
agp1.fmsd 1.02.10
3
Содержание
ПРЕДИСЛОВИЕ
2
СОДЕРЖАНИЕ
11
1
ВВЕДЕНИЕ
12
2
ФОРМАЛЬНЫЕ СПЕЦИФИКАЦИИ И РАЗРАБОТКА ПО
2.1 Унифицированный язык моделирования UML . . . .
2.1.1 Язык блок - схем . . . . . . . . . . . . . . . . .
2.1.2
Потоки данных и проектирование структуры
программы . . . . . . . . . . . . . . . . . . . . .
2.1.3 Пакет визуализации графов . . . . . . . . . . .
2.1.4 Диаграмма состояний . . . . . . . . . . . . . . .
2.1.5 SchemaSpy и схема реляционных связей БД . .
2.1.6 Форма Бэкуса — Наура (БНФ) . . . . . . . . . .
2.1.7 Doxygen и диаграммы классов . . . . . . . . . .
2.1.7.1
Создание отчетов в виде HTML страниц
. . . . . . . . . . . . . . . . . . . . . . .
2.1.7.2
Диаграммы Doxygen-а и UML
. . . . . . . . . . . . . . . . . . . . . . .
2.1.7.3 Построение файла справки Микрософт
. . . . . . . . . . . . . . . . . . . . . . .
2.1.7.4
Улучшение текста отчета
. . . . . . . . . . . . . . . . . . . . . . .
2.1.7.5
Дополнительные команды
. . . . . . . . . . . . . . . . . . . . . . .
2.2 Система компьютерной верстки LaTex . . . . . . . . .
2.2.1 Преамбула и структурные части документа . .
2.2.2 Предметный указатель . . . . . . . . . . . . . .
2.2.3 Библиография . . . . . . . . . . . . . . . . . . .
2.3 Проектирование ПО и LaTex . . . . . . . . . . . . . . .
2.3.1 Проектирование и тестирование ПО . . . . . . .
14
16
18
20
23
27
35
36
37
37
41
45
47
48
51
52
55
56
61
61
agp1.fmsd 1.02.10
4
2.3.2
2.3.3
65
67
Требования к ПО . . . . . . . . . . . . . . . . .
Абстрактные типы данных . . . . . . . . . . .
2.3.3.1
Очереди и стеки
. . . . . . . . . . . . . . . . . . . . . . .
2.3.3.2
Кольцо целых – создание типа и математика
. . . . . . . . . . . . . . . . . . . . . . .
2.3.4 Математический режим LaTex-а . . . . . . . . .
2.3.4.1
Математические символы LaTex-а
. . . . . . . . . . . . . . . . . . . . . . .
2.4 Проектирование по контракту . . . . . . . . . . . . . .
2.4.1 Требования к модулям и связям между ними .
2.4.2 Композиционный анализ . . . . . . . . . . . . .
2.4.3 Категории функциональных типов контракта .
2.4.3.1
Терминология, используемая в литературе
. . . . . . . . . . . . . . . . . . . . . . .
2.4.4 Категоричность и полнота спецификации . . . .
2.4.4.1
Полнота спецификации и метод разработки RAISE
. . . . . . . . . . . . . . . . . . . . . . .
2.4.4.2
Понятие категоричности
. . . . . . . . . . . . . . . . . . . . . . .
2.5 Применение языка формальных спецификаций RSL .
2.5.1 Утилита RSLTC . . . . . . . . . . . . . . . . . .
2.5.1.1 Варианты командной строки утилиты
RSLTC
. . . . . . . . . . . . . . . . . . . . . . .
2.5.2 Спецификации языка RSL . . . . . . . . . . . .
2.5.2.1
Декларации переменных
. . . . . . . . . . . . . . . . . . . . . . .
2.5.2.2
Декларации величин и функций
. . . . . . . . . . . . . . . . . . . . . . .
2.5.2.3
Расширение схем
. . . . . . . . . . . . . . . . . . . . . . .
69
70
71
74
76
77
83
85
86
87
88
89
91
91
93
93
94
95
96
agp1.fmsd 1.02.10
2.5.2.4
2.5.3
2.5.4
2.5.5
2.5.6
5
Конструирование типов
. . . . . . . . . . . . . . . . . . . . . . . 97
2.5.2.5
Тестовые варианты
. . . . . . . . . . . . . . . . . . . . . . . 98
2.5.2.6
Таблицы обозначений
. . . . . . . . . . . . . . . . . . . . . . . 99
Спецификация целых чисел Пеано . . . . . . . 101
Выражения языка RSL . . . . . . . . . . . . . . 104
2.5.4.1
Выражение skip
. . . . . . . . . . . . . . . . . . . . . . . 104
2.5.4.2
Выражение let
. . . . . . . . . . . . . . . . . . . . . . . 105
2.5.4.3
Условное выражение if- else
. . . . . . . . . . . . . . . . . . . . . . . 105
2.5.4.4
Выражение case
. . . . . . . . . . . . . . . . . . . . . . . 106
Общий порядок разработки ПО . . . . . . . . . 107
Императивные конструкции языка RSL . . . . . 109
2.5.6.1 Функции с доступом к переменным модуля
. . . . . . . . . . . . . . . . . . . . . . . 110
2.5.6.2
Локальные переменные и присваивание
. . . . . . . . . . . . . . . . . . . . . . . 110
2.5.6.3
Конструкция ветвления if
. . . . . . . . . . . . . . . . . . . . . . . 111
2.5.6.4
Цикл while
. . . . . . . . . . . . . . . . . . . . . . . 111
2.5.6.5
Цикл until
. . . . . . . . . . . . . . . . . . . . . . . 111
2.5.6.6
Цикл for
. . . . . . . . . . . . . . . . . . . . . . . 111
2.5.6.7 Использование императивных конструкций
. . . . . . . . . . . . . . . . . . . . . . . 112
agp1.fmsd 1.02.10
6
2.5.7
2.5.8
2.5.9
Операции над классами . . . . . . . . . . . . . . 114
Схемы с параметрами . . . . . . . . . . . . . . . 115
Пример спецификации проекта Гавань . . . . . 115
2.5.9.1
Цели примера
. . . . . . . . . . . . . . . . . . . . . . . 117
2.5.9.2
Требования к функциональности системы
. . . . . . . . . . . . . . . . . . . . . . . 117
2.5.9.3
Начальная постановка задачи
. . . . . . . . . . . . . . . . . . . . . . . 118
2.5.9.4
Краткий план разработки
. . . . . . . . . . . . . . . . . . . . . . . 123
2.6 Утилита RSLTC – не только проверка синтаксиса . . . 128
2.6.1 Условия уверенности . . . . . . . . . . . . . . . 129
2.6.2 Проверка реализации класса . . . . . . . . . . . 132
2.6.2.1
Изменение описания функции
. . . . . . . . . . . . . . . . . . . . . . . 134
2.6.2.2
Изменение описания типа
. . . . . . . . . . . . . . . . . . . . . . . 135
2.6.2.3
Пропущенная функция в реализации
. . . . . . . . . . . . . . . . . . . . . . . 136
2.6.3 Генерация зависимости модулей спецификации 137
3
ЛАБОРАТОРНЫЙ ПРАКТИКУМ
137
3.1 Состояние конечного автомата . . . . . . . . . . . . . . 137
3.2 Отчет для Doxygen . . . . . . . . . . . . . . . . . . . . 138
3.3 Первый отчет для LaTex . . . . . . . . . . . . . . . . 139
3.4 Иерархия классов .Net . . . . . . . . . . . . . . . . . . 139
3.5 Требования к данным . . . . . . . . . . . . . . . . . . 140
3.6 Требования к приложению . . . . . . . . . . . . . . . . 141
3.7 Формальная спецификация функции . . . . . . . . . . 142
3.8 Формальная спецификация абстрактного типа данных 143
3.9 Спецификация приложения . . . . . . . . . . . . . . . 144
3.10 Экспериментальные лабораторные . . . . . . . . . . . 145
3.10.1 Требования к задаче Г.Майерса о треугольниках145
agp1.fmsd 1.02.10
7
3.10.2 Требования и спецификация приложения . . . 145
3.10.3 Требования и спецификация системы Учет успеваемости . . . . . . . . . . . . . . . . . . . . . . . 146
3.10.4 Диагональное произведение (соединение) и операторы Чёрча . . . . . . . . . . . . . . . . . . . . 147
3.10.5 Полнота спецификации Стека-Очереди . . . . . 148
3.10.6 Доклад по не обсужденным и новым возможностям Doxygen . . . . . . . . . . . . . . . . . . . 149
3.10.7 Требования и спецификация системе Тестирование работ . . . . . . . . . . . . . . . . . . . . . 149
3.10.8 Описание и Реализация типа Арифметика Пеано149
3.11 Вопросы . . . . . . . . . . . . . . . . . . . . . . . . . . 150
3.11.1 Первая группа вопросов . . . . . . . . . . . . . 150
3.11.2 Вторая группа вопросов . . . . . . . . . . . . . 152
4
ПРИМЕРЫ
155
4.1 Преамбула настоящего документа . . . . . . . . . . . 155
4.2 Примеры спроектированной архитектуры . . . . . . . 157
4.3 Препроцессор mkTex . . . . . . . . . . . . . . . . . . . 165
5
СЛОВАРЬ
167
ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ .
СПИСОК ЛИТЕРАТУРЫ . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. 175
.
.
. 185
A
Исходные тексты проект Hello
186
B
Файл настройки Doxygen-а для проекта Hello
188
C
Пример файла пояснительной записки
213
D
Диаграммы графов связей Doxygen-а
218
E
Примеры диаграмм состояний
221
E.1 Примеры узлов пакета визуализации графов . . . . . . 221
agp1.fmsd 1.02.10
8
E.2
E.3
E.4
E.5
E.6
Примеры стрелок пакета визуализации графов . . . . 222
Диаграмма состояний окна OkCancel . . . . . . . . . . 223
Диаграмма состояний ’Ввод данных’ . . . . . . . . . . 224
Диаграмма состояний главного окна приложения . . . 226
Диаграмма состояний главного окна приложения без
подавтомата . . . . . . . . . . . . . . . . . . . . . . . . . 227
E.7 Еще одна диаграмма состояний главного окна приложения . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
E.8 Диаграмма состояний дочернего окна представления
табличных данных . . . . . . . . . . . . . . . . . . . . . 229
E.9 Диаграмма состояний модального окна отношение одинко-многим . . . . . . . . . . . . . . . . . . . . . . . . . . 230
F
Язык формальных спецификаций Z
232
F.1 Утилита ZTC и язык формальных спецификаций Z . 232
F.1.1 Утилита ZTC . . . . . . . . . . . . . . . . . . . . 232
F.1.1.1 Замеченные недостатки
. . . . . . . . . . . . . . . . . . . . . . . 235
F.1.1.2 Проверка синтаксиса и первая схема
на Z
. . . . . . . . . . . . . . . . . . . . . . . 238
F.1.1.3 ZTC и вещественные числа
. . . . . . . . . . . . . . . . . . . . . . . 240
F.1.1.4 Замечания по объемным спецификациям
. . . . . . . . . . . . . . . . . . . . . . . 241
F.1.2 Z и описание данных . . . . . . . . . . . . . . . 244
F.1.2.1 Имя
. . . . . . . . . . . . . . . . . . . . . . . 244
F.1.2.2 Текстовое представление целого числа
. . . . . . . . . . . . . . . . . . . . . . . 246
F.1.2.3 Текстовое представление вещественного числа
. . . . . . . . . . . . . . . . . . . . . . . 247
F.2 Введение в язык Z . . . . . . . . . . . . . . . . . . . . . 249
agp1.fmsd 1.02.10
F.2.1
9
Логика предикатов . . . . . . . . . . . . . . . . 249
F.2.1.1 Логика высказываний
. . . . . . . . . . . . . . . . . . . . . . . 249
F.2.1.2 Квантификация
. . . . . . . . . . . . . . . . . . . . . . . 250
F.2.1.3 Законы
. . . . . . . . . . . . . . . . . . . . . . . 251
F.2.2 Множества и отношения . . . . . . . . . . . . . 251
F.2.2.1 Типы
. . . . . . . . . . . . . . . . . . . . . . . 251
F.2.2.2 Множества
. . . . . . . . . . . . . . . . . . . . . . . 253
F.2.2.3 Операции над множествами
. . . . . . . . . . . . . . . . . . . . . . . 255
F.2.2.4 Обобщение операций над множествами
. . . . . . . . . . . . . . . . . . . . . . . 257
F.2.2.5 Сокращенное определение множества
. . . . . . . . . . . . . . . . . . . . . . . 257
F.2.2.6 Подмножества
. . . . . . . . . . . . . . . . . . . . . . . 259
F.2.2.7 Множества и высказывания
. . . . . . . . . . . . . . . . . . . . . . . 259
F.2.2.8 Опять про операции над множествами
. . . . . . . . . . . . . . . . . . . . . . . 260
F.2.2.9 Прямое произведение множеств
. . . . . . . . . . . . . . . . . . . . . . . 261
F.2.2.10 Пересмотр сокращенного определения
множества
. . . . . . . . . . . . . . . . . . . . . . . 263
F.2.2.11 Степень множества
. . . . . . . . . . . . . . . . . . . . . . . 264
F.2.2.12 Отношения
. . . . . . . . . . . . . . . . . . . . . . . 265
F.2.3 Функции и операции над ними . . . . . . . . . . 268
agp1.fmsd 1.02.10
F.2.3.1
10
Функции
. . . . . . . . . . . . . . . . . . . . . . . 268
F.2.3.2 Реляционные операции над функциями
. . . . . . . . . . . . . . . . . . . . . . . 270
F.2.4 Числа и последовательности . . . . . . . . . . . 272
F.2.4.1 Числа
. . . . . . . . . . . . . . . . . . . . . . . 273
F.2.4.2 Арифметика
. . . . . . . . . . . . . . . . . . . . . . . 273
F.2.4.3 Итерация
. . . . . . . . . . . . . . . . . . . . . . . 275
F.2.4.4 Диапазоны чисел
. . . . . . . . . . . . . . . . . . . . . . . 276
F.2.4.5 Мощность множества
. . . . . . . . . . . . . . . . . . . . . . . 276
F.2.4.6 Опять о типах
. . . . . . . . . . . . . . . . . . . . . . . 277
F.2.4.7 Последовательности
. . . . . . . . . . . . . . . . . . . . . . . 279
F.2.4.8 Конкатенация
. . . . . . . . . . . . . . . . . . . . . . . 281
F.2.4.9 Префикс
. . . . . . . . . . . . . . . . . . . . . . . 281
F.2.4.10 Остальные операции на последовательностях
. . . . . . . . . . . . . . . . . . . . . . . 283
F.2.4.11 Обратный порядок последовательности
. . . . . . . . . . . . . . . . . . . . . . . 285
F.2.4.12 Распределенная форма операций
. . . . . . . . . . . . . . . . . . . . . . . 286
F.2.4.13 Разделимость и покрытие
. . . . . . . . . . . . . . . . . . . . . . . 286
agp1.fmsd 1.02.10
F.3
F.4
F.5
F.6
F.7
11
F.2.4.14 Порядок
. . . . . . . . . . . . . . . . . . . . . . . 287
F.2.4.15 Заключение
. . . . . . . . . . . . . . . . . . . . . . . 288
F.2.5 Схемы . . . . . . . . . . . . . . . . . . . . . . . . 289
F.2.5.1 Пример спецификации
. . . . . . . . . . . . . . . . . . . . . . . 292
F.2.5.2 Операторы над схемами
. . . . . . . . . . . . . . . . . . . . . . . 299
F.2.5.3 Свойства
. . . . . . . . . . . . . . . . . . . . . . . 303
F.2.6 Привычные типы, не встроенные в язык Z . . . 303
F.2.7 Императивный стиль . . . . . . . . . . . . . . . 304
F.2.8 Выводы . . . . . . . . . . . . . . . . . . . . . . . 305
Краткий справочник по символам языка Z . . . . . . 305
F.3.1 Структура спецификации . . . . . . . . . . . . . 310
F.3.1.1 Раздел Zed
. . . . . . . . . . . . . . . . . . . . . . . 310
F.3.1.2 Комментарии
. . . . . . . . . . . . . . . . . . . . . . . 312
F.3.1.3 Аксиомы
. . . . . . . . . . . . . . . . . . . . . . . 312
F.3.1.4 Шаблоны
. . . . . . . . . . . . . . . . . . . . . . . 313
F.3.1.5 Схемы
. . . . . . . . . . . . . . . . . . . . . . . 314
F.3.1.6 Синтаксис
. . . . . . . . . . . . . . . . . . . . . . . 314
Подключение тестовой спецификации . . . . . . . . . . 315
Z и шаблоны схем . . . . . . . . . . . . . . . . . . . . . 325
Абстрактная форма спецификации Книга Дней Рождений . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
Императивная форма спецификации Книга Дней Рождений . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
agp1.fmsd 1.02.10
1
12
ВВЕДЕНИЕ
Термин программное обеспечение в словаре международной организации по стандартам [14, 4.1085] трактуется как ’программы, процедуры, правила и любая соответствующая документация, относящиеся к работе вычислительной системы’. Далее, формальная спецификация – это математическое описание программной или аппаратной
системы, которая может быть реализована в соответствии с этим
описанием и она должна входить в любую соответствующую документацию, в любой момент жизненного цикла ПО (развитие рассматриваемой системы во времени, начиная от замысла и заканчивая списанием, [14, 4.339]) и в каждом соответствующем документе
(включая код) должна быть по мере возможности одинаковой.
Одним из первых необходимость одновременной разработки ПО и
документации к нему заметил Д.Кнут, разработавший систему компьютерной верстки Tex (см. [84, стр.6]), и придумавший литературное программирование (грамотное программирование). Такую методологию программирования и документирования, в которой программа состоит из текста на естественном языке и кодом на языках
программирования. Методология реализует на практике принцип самодокументирования. При таком подходе документация и код удается разрабатывать одновременно. Точнее, сначала пишется текст на
естественном языке – документация, а потом – код. И желательно,
что бы ’соответствующая документация’ создавалась из кода ПО.
При этом подразумевается, что ’текст на естественном языке’ должен включать в себя псевдокод, так как он в сокращенном виде комментирует и объясняет текст программ. На комментирование текста программ при помощи псевдокода указывают многие авторы. В
языке Eiffel Б.Мейера такие комментарии являются частью кода. А
в [85, стр.209] есть целая глава ’Процесс программирования с псевдокодом’.
Замечание
То есть, предлагается придумать стройную систему ASCII -
agp1.fmsd 1.02.10
13
обозначений, потом её не забыть. Потом уговорить окружающих их запомнить. Потом уговорить того, кто запомнит эти
чудные обозначения, читать свои замечательные комментарии
с целью поиска ошибок ((;.
В текущем отчете вместо использования псевдокода предполагается использовать язык формальных спецификаций. В отчете обсуждаются два таких языка: RSL ([32]) и Z ([20]). В обоих случаях были разработаны специальные утилиты проверки правописания
([14, 4.554], grammar checker) и по два вида обозначений для каждого
языка: ASCII - вид непосредственно для кода на языке программирования, и LaTex - вид для генерации документации при помощи
системы LaTex, как более удобный математикам. В случае RSL это
утилита [6, RSLTC], в случае Z это утилита cite[ZTC]ZTC. Для преобразования из ASCII - вид в вид для LaTex требуются не слишком
сложные усилия.
В [75] утилита ZTC использовалась для формулировки заданий,
в [81] – как иллюстрация для метода проектирования по контракту при разработке маленького класса. В разделе 2.5.3 приводятся
небольшая спецификация целых чисел Пеано, обоими видами.
Б.Мейер в своем языке Eiffel добился (по его словам, см. [60,
стр.47],[4]) постепенного развития проекта от постановки задачи до
рабочей версии программы с построением документации прямо из
кода программ. То есть, реализовал принцип самодокументирования
ПО на практике. Причем спецификация для язык Eiffel одновременно представляет собой будущий код. Таким образом, можно считать,
что само проектирование ПО выполняется до, собственно, кодирования в смысле языка Си или С#.
В остальных случаях, на практике доступны утилиты, предоставляющие некоторые частичные возможности документирования ПО.
Некоторые из них будут рассмотрены в этом документе.
agp1.fmsd 1.02.10
2
14
ФОРМАЛЬНЫЕ СПЕЦИФИКАЦИИ И РАЗРАБОТКА ПО
Спецификация
В формальных методах разработки ПО спецификацией в абстрактном стиле называется точное описание свойств ПО, без
излишних преждевременных подробностей. В силу требования
точности - часто используются математическая нотация, в силу
отсутствия подробностей - подразумевается, что спецификация
должна отвечать на вопрос ’Что надо сделать?’ и не отвечать
на вопрос ’Как это делать?’.
На рисунке [60, стр.24] приводится статистика по стоимости сопровождения ПО. 42 % стоимости занимает изменения требований заказчика и 17,6 % изменения в форматах данных (которые тоже можно
трактовать как изменение требований). То есть, 60 % работы во время
сопровождения уходит на переделку ПО, которое влечет переделку
документации к нему. Не будет слишком большим допущением считать, что аналогичное количество усилий на переделку ПО придется
потратить и за время разработки этого ПО (а сюда еще нужно добавить время на переделку неправильно поставленных и неправильно
понятых заданий).
Чем больше написано в спецификации – тем больше
придется переделывать. Толкование слова ’абстрактный’
– это отвлечённый, не связанный с непосредственным восприятием реального мира, должно уяснить смысл термина абстрактный стиль спецификации. Поскольку абстрактная спецификация не связана с непосредственным
восприятием реального мира, она не должна подвергаться слишком большим изменениям при изменении непосредственного восприятия этого реального мира.
agp1.fmsd 1.02.10
15
Таким образом, спецификации требуется писать в максимально обобщенной форме, выдерживающей будущие бесконечные изменения.
Но, при этом, спецификация должна содержать полезную информацию. У термина абстрактная спецификация существуют синонимы:
неявный стиль спецификации или аппликативный стиль спецификации. Последний синоним происходит от слова apply – применять
(причем подразумевается применение функций).
Хорошим примером абстракции совершенно не связанной с непосредственным восприятием реального мира является число нуль. И
одно из его свойства задаются в неявной, аппликативной форме:
∀x : R ⇒ x + 0 = x
при помощи применения функции сложения.
Стиль, в котором записываются наиболее абстрактные спецификации, называется аппликативным. Текст такой спецификации похож на применение математических функций (applicate – применять), в нем отсутствуют переменные и не могут быть описаны побочных эффекты вычислений. Он хорошо подходит для описания
абстрактных типов данных в [60, 4]. С другой стороны, рано или
поздно возникает необходимость описать алгоритм некоторых вычислений. Если требуемый алгоритм не может быть представлен в
виде хвостовой рекурсии, то изложение его в аппликативном стиле представляет собой нетривиальную проблему. В отчете [81, Алгоритм итератора] приводится пример двух версий алгоритма итератора на языке Z. Считается, что более привычные для программистов
тексты спецификаций, нужно писать в императивном стиле (императив – это безусловное повеление). Тексты спецификаций содержат
описание переменных и конструкции для циклов.
Поскольку система компьютерной верстки LaTex создана для
записи математических текстов, то её обозначения можно использовать как псевдокод в программах. Но отличается система записи
LaTex , как уже было отмечено выше, от языков формальных спецификаций тем, что его нотация выглядит избыточно громоздкой и
для него не обнаружены средства поиска ошибок в формулах.
agp1.fmsd 1.02.10
16
Далее, к языкам формальных спецификаций, с некоторой натяжкой, можно отнести:
• унифицированный язык моделирования UML (см.[47]);
• язык запросов SQL (см.[52, 77]);
• язык любого программного средства, которое позиционируется как средство прототипирования программных комплексов
(например, MATLAB или TCL/TK), может рассматриваться и
использоваться как язык формальной спецификации (см.[28]).
2.1
Унифицированный язык моделирования UML
Графический язык UML предназначается для визуализации, специфицирования, конструирования и документирования систем, в которых большая роль принадлежит программному обеспечению, с претензией на универсальность и объектно - ориентированное проектирование. Из достаточно часто изпользуемых видов UML- диаграмм
можно перечислить следующие:
• блок - схемы: традиционно используются для описания алгоритмов;
• потоки данных: абстракция, которая используется для описания изменения данных в процессе обработки некоторым ПО;
• диаграммы состояний;
• схемы реляционных связей в БД;
• диаграммы автоматов, их удобно использовать для описания
классов (см.[47, стр.322]);
• диаграммы иерархии классов;
• и многие другие.
agp1.fmsd 1.02.10
17
При этом, в силу заявки на универсальность UML, в него были добавлено большое количество возможностей имеющие мало общего
общего с обьектной- ориентированностью. В результате этого и в
силу неопределенности самого процесса проектирования и неопределенности понятия объектной- ориентированности сам UML выглядит
несколько переусложненным и не слишком пригодным к использованию в качестве языка спецификаций.
Замечание 1
См. [47, стр.128]: прямое проектирование (forward engineering)
-– это процесс трансформации модели в код посредством отображения на язык реализации. В результате прямого проектирования происходит потеря информации, поскольку модели, описанные на UML, семантически богаче, чем любой современный
объектно- ориентированный язык программирования.
То есть, на UML- диаграммах есть не нужная для разработчика информация и нет ясности какими средствами языка программирования выполнять кодирование. Например, С.Мейерс в [61, Правило 38]
считает композицию и агрегацию синонимами, то есть, не различает их. Их надо программировать одинаково. А на UML- диаграммах
они рисуются по разному.
Полезные соглашения для UML- диаграмм можно позаимствовать из монографии [60, стр.701,707]:
• классы изображаются эллипсами;
• методы или атрибуты отмечаются текстом возле эллипса;
• отношение наследовать изображается линией со стрелкой в сторону базового класса;
• отношение использовать изображается двойной линией со стрелкой в сторону используемого класса;
• абстрактный метод или класс отмечается звездочкой;
agp1.fmsd 1.02.10
18
• реализация абстрактного метода или класса отмечается одним
плюсом;
• переопределяемый метод отмечается двумя плюсами.
На практике, в связи с наличием программных средств, позволяющих по коду программы строить UML- диаграммы, его вполне
можно использвать для иллюстраций, пояснений или описания уже
готового программного обеспечения. К таким доступным свободнораспостраняемым продуктам относятся:
• пакет визуализации графов GraphViz (см.https://graphviz.
org/, [3]);
• SchemaSpy и др. – графический обозреватель метаданных схемы базы данных (см.https://schemaspy.sourceforge.net/).
• Doxygen – кроссплатформенная система документирования исходных текстов (см. https://www.doxygen.nl/, [8, 69]),
2.1.1
Язык блок - схем
Язык блок - схемы (англ. - flowchart) является полуформальным языком. Поэтому из подробного описание блок - схем, изложенного в
[45], можно использовать только шесть следующих элементов и жить
долго и счастливо:
• Символ начала (начальный терминатор, англ. start):
.
Тут начинается путешествие;
• Символ окончания (конечный терминатор, англ. finish):
.
agp1.fmsd 1.02.10
19
Тут заканчивается путешествие;
• Символ перехода на другую страницу: маленький кружочек с
номером. При попадании на него, надо перевернуть страницу и
искать такой же кружок с таким же числом, из кружка должна
выходить стрелка.
• Символ действия:
.
Одна стрелка входит и только одна стрелка выходит;
• Символ выбора:
.
Тут одна стрелка входит, в ромбике задается вопрос, из ромбика выходит стрелка Да (Yes) и выходит стрелка Нет (No);
• Символ комментария:
.
Тут описываются действующие лица и исполнители.
Вся сказочка про добра молодца представляет собой следующую
картинку, в которой надо перемещаться по стрелкам:
agp1.fmsd 1.02.10
20
Рисунок 2.1 – История одного путешествия
Замечание
Все блок - схемы из документа были набраны любезно предоставленным сервисом на сайте: https://app.diagrams.net/.
Сервис не требует авторизации и позволяет редактировать блок
- схемы, которые можно хранить на локальном диске.
2.1.2
Потоки данных и проектирование структуры программы
Поток данных – часто используемое, как бы очевидное понятие без
особого определения. Под потоком данных может пониматься от-
agp1.fmsd 1.02.10
21
дельный файл (формат которого описан в соответствующем месте
технической документации), или некоторая запись или набор значений фактических параметров функции (или подпрограммы). Про
поток данных можно сказать, что он имеет направление и некоторую
структуру. Эта структура обычно меняться при продвижении данных между отдельными частями ПО. Далее приводится несколько
примеров.
На рис. 2.4 потоки данных изображается стрелками, которые обозначают попадание информации от компьютера к человеку и наоборот через соответствующие устройства и органы чувств. Никак не
акцентируется внимание на структуре этих потоков.
На рис. 2.2 [79, ЛАБОРАТОРНАЯ РАБОТА: КОНВЕРТОР ТРЕКА] стрелка потока данных обозначает просто передачу параметров
из функции в объект с координатой и обратно. В этом случае потоки обладают конкретной, уже запрограммированной структурой. В
одних случаях – это строка символов. В других – это массив чисел
с плавающей точкой.
Рисунок 2.2 – Преобразование координат
agp1.fmsd 1.02.10
22
Рис. 2.3 – более сложный. На нем изображены потоки данных
информационной системы по сбору статистики об использованию её
ресурсов. Эллипсы – это приложения, а прямоугольники – файлы
соответствующей структуры. Приложение WSMntSvc.exe с заданым
интервалом выполняет запуск командного фала ex mkLoad.cmd. Командный файл последовательно вызывает парсер системных журналов и утилиту SQL-сервера. Парсер системных журналов LogParser
вынимает нужную информацию об активности клиентв и записывает её в CSV- файл. Затем утилита isql загружает содержимое этого в
файла в таблицы SQL- сервера. Запускаемое интерактивно приложение adminTool из этих таблиц строит различные отчеты, в частности
выставляет счета клиентам за использованные ресурсы информационной системы.
Рисунок 2.3 – Поток данных в системе сбора статистики
На ранних этапих проектирования будущего приложения или информационной системы обозначения потоков (возле стрелок или как
на рис.2.3 – в прямоугольниках) в языках формальной спецификации могут использоваться как неопределяемые типы (см. 2.5.2.4). И
в ходе дальнейшего проектирования эти типы будут конкретизироваться.
Понятие потока данных играет очень важную роль в специальном методе проектирования ПО, которое называется композиционным (см. [48, Проектирование структуры программы], [58]).
agp1.fmsd 1.02.10
2.1.3
23
Пакет визуализации графов
Пакет (см. [70, 3]) содержит несколько утилит dot.exe, circo.exe и др.,
которые при помощи языка визуализации графов отображают некоторый текст в графические файлы с различного вида диаграммами.
Следующий текст является примером для изображения потоков данных между пользователем компьютера и компьютером:
---- File:./pics/comp/exchange1251.dot
digraph world {
{rank = same;
{rank = same;
{rank = same;
input}
brain; User;
output}
System; database}
User -> brain;
brain -> User;
User ->input:m[fontcolor=blue, label=""];
User -> input:i[fontcolor=blue, label=""];
User -> input:n [fontcolor=red, label=""];
input:p -> System;
input:so -> System;
input:mo -> System;
System -> output:pi;
System -> output:ssi;
output:po -> User;
output:sso -> User;
System -> database[label="интерфейс\n базы данных"];
database -> System;
input [shape=record,
label="{{<p> |keyboard| <n> } |{<so> |screen | <m>}| {<mo>| mouse|<i> } }"]
output [shape=record, label="{{<pi>| printer | <po>} | { <ssi>|screen|<sso> } }"]
}
---- End Of File:./pics/comp/exchange1251.dot
Это программа после компиляции утилитой circo.exe из пакета dot
выглядит следующим образом:
agp1.fmsd 1.02.10
24
Рисунок 2.4 – Работа человека за компьютером
В дистрибутив пакет визуализации графов входит
• значительное количество утилит. В Doxygen из них используется утилита dot.exe (circo.exe). Это утилита, которая из текстового описания графа, сделанного на достаточно понятном
языке описания графов – DOT [3] , строит файлы популярных
форматов, в частности png, jpg, ps и т.д.;
• самостоятельный интерес представляют утилиты для визуального редактирования и просмотра графов – dotty.exe и gvedit.exe;
• набор руководств пользователя по всем утилитам;
• большого количества разнообразных примеров графов, сделанных на языке DOT;
• API интерфейс для использования возможностей Graphviz в
приложениях, написанных на языке Си;
• описание API интерфейса находится по адресу http://www.
graphviz.org/pub/graphviz/CURRENT/doxygen/html/;
agp1.fmsd 1.02.10
25
• Файлы для утилит пакета с национальными текстами должны
готовится в кодировке utf-8.
При создании графа используются узлы (англ. node) и стрелки
(англ. edge). Направление стрелок графа задает атрибутом rankdir,
параметр LR означает слева-направо, TB – сверху-вниз. Размер листа для графа задается атрибутом size, в дюймах. Первое число –
ширина, второе – высота листа.
rankdir=LR; //
size="12,16";
ratio=fill;
rankdir=TB;
Атрибут ratio с параметром fill подгоняет размер графа под размер
листа. Узлы соединяются стрелками. Узлы и стрелки могут иметь
наборы атрибутов. Атрибуты задаются рядом с узлом или стрелкой в квадратных скобках. Меняя параметры атрибутов можно изменять вид узлов, стрелок и самого графа. Один из главных атрибутов – label используется для подписей возле стрелки или внутри
узла. Причем подписи можно делать многострочными, если между
словами подписи вставлять служебные символы \n (центрирование
текста), \r (выравнивание текста вправо), \l (выравнивание текста
влево).
Узлы могут объединяться в подграфы (англ. subgraph). В подграфе можно задавать одинаковые параметры узлам (и, наверно,
стрелкам).
subgraph "c_1" { a; b; }
Существуют специальные подграфы, которые называются кластерами (англ. cluster). Имя кластера должно начинаться на слово cluster.
subgraph "cluster_1" { label="1"; a; b; }
Узлы кластера будут располагаться рядом. Кластер может иметь
метку.
Примеры узлов можно посмотреть на следующем рисунке (исходный код см. раздел E.1):
agp1.fmsd 1.02.10
26
Рисунок 2.5 – Примеры узлов
На рис. 2.5 почти каждый узел подписан значением атрибута
shape. Например, узел состояние автомата задается следующим образом:
rBox[shape=box, style=rounded];
Примеры стрелок представлены на следующем рисунке (исходный код см. раздел E.2):
agp1.fmsd 1.02.10
27
Рисунок 2.6 – Примеры стрелок
На рис. 2.6 для каждой стрелки выведено значение атрибута
arrowhead:
c ->d [arrowhead=crowodot;
label=crowodot; ];
И только для пунктирной стрелки используется атрибут style:
c0->d0[arrowhead=normal; label=dotted; style=dotted];
а для стрелки back используется атрибут dir:
d1->a1[
color=blue;
dir=back;
label=back];
Кроме того, атрибут dir может иметь значение both, тогда стрелка
будет указывать в обоих направлениях.
2.1.4
Диаграмма состояний
На диаграмме состояний отображаются:
• Состояние – состояние автомата, в котором он может выполнять деятельность (гм, прямоугольник с закругленными углами);
agp1.fmsd 1.02.10
28
• Событие – событие инициирует переход из состояние в состояние (подпись над стрелкой или ромбик, если событие приводит
к переходу в несколько состояний);
• Переход – переход из состояния в состояние (стрелка). Стрелка обычно подписывается событием, которое вызвало переход
автомата в другое состояние;
• Деятельность – несколько действий, изображается внутри состояния, могут быть пометки enter/действия (выполняется на
входе в автомат), exit/действия (выполняется на выходе из автомата), [do/]действия и т.д.;
• Действие – особенно важное действие связанное с передачейполучением данных чему-то внешнему или от чего-то внешнего;
С некоторыми заменами символов языка UML пакет GraphViz можно
использовать для создания диаграмм состояний. С помощью диаграмм состояний (англ. – state machine) достаточно удобно представлять элементы интерфейса пользователя системы или приложения.
Для этого потребуются следующие обозначения:
• Символ начального состояния (на стрелке от начального состо.
яния можно подписать получение начальных данных):
• Символ конечного состояния:
.
• Символ состояния (и деятельности в нем):
.;
• Символ события – ромб (для интерфейса подразумевается внешнее событие), если есть ветвление, иначе просто стрелка:
.
Перед ромбом ставится метка, которая уточняет, где произошло событие, после ромба – какое событие. На рис. 2.7 при
agp1.fmsd 1.02.10
29
щелчке пользователем на кнопку Ok, или Cancel, или крестик
в правом верхнем углу окна автомат переходит к действию и
другому состоянию. Желательно, что бы варианты щелчков
располагались в порядке соответствующем их расположению в
окне приложения;
. В прямоугольнике описы• Важное действие автомата:
ваются действия – на рис. 2.7, диалоговое окно вернет признак
Ok в вызвавшую его функцию.
• Подавтоматы в автомате пока не удается изображать легким
путем. Для подавтоматов будет использоваться следующий символ:
.
Таким образом, диаграмма с окном для вопроса (см. [76, 64, Диалоговое окно OkCancel]) может выглядеть следующим образом:
Рисунок 2.7 – Окно вопроса/Ок-Cancel
agp1.fmsd 1.02.10
30
В окне демонстрируется вопрос пользователю приложения. Пользователь выполняет щелчок на кнопках Ок, Cancel или управляющем элементе с крестиком вверху-справа на модальном окне. В зависимости от щелчка окно возвращает признак в вызывающую программу. Исходный код и пояснения к нему см. E.3.
Следующее окно – ’Ввод данных’ (см. [76, 64, Диалоговое окно
ввод данных]) имеет более сложную диаграмму:
Рисунок 2.8 – Окно ввод данных
В начальном состоянии задается список полей с умолчательными
значениями. В первое поле можно вводить данные. Как и в предыдущем окне вопроса, щелчок по управляющим элементам изображается отдельно и ведет к завершению работы автомата. Ввод данных
с клавиатуры (ромбик Input) приводит либо к переходу к следующему полю, либо к редактированию текущего поля (если пользователь
ввел корректные данные), либо к блокированию поля (если пользователь ввел некорректные данные). При блокированном поле можно
либо принудительно закрыть окно, либо ввести корректные данные.
Введенные данные передаются в вызывающую программу при щелч-
agp1.fmsd 1.02.10
31
ке на кнопке Ok. Исходный код и пояснения к нему см. E.4.
Для главного окна приложения будет представлено несколько вариантов. Первая схема – сложная версия главного окна приложения
(см. [76, 64, Меню в главном окне приложения]). Исходный код и
пояснения к нему см. E.5. В автомате в качестве пробы расположен
подавтомат – окно ’О себе’ (About, это упрощенная версия окна вопроса):
Рисунок 2.9 – Главное окно приложения с подавтоматом
Стрелки, отображаемые красным цветом, добавлены что бы добиться хорошего расположения узлов. На деле красный цвет заменяется на белый. Оба кластера для главного окна и для окна сообщения удавалось расположить на одном уровне только после того как
в кластере окна сообщения стрелки были направлены в обратную
сторону. Например:
abtIn -> click[color=black; dir=back];
agp1.fmsd 1.02.10
32
Тут стрелка выходит из узла входа в подавтомат и входит в узел
щелчка в главном меню. Расположение стрелки приводится к требуемому виду при помощи атрибута dir.
Поскольку добавление подавтомата получалось слишком трудоемко, то диаграмма не доработана. На ней не показано закрытие
дочернего окна. На ней не показано, что при дочернем окне опять
можно щелкнуть на меню about.
Следующая схема – простая версия главного окна приложения.
Исходный код и пояснения к нему см. E.6. В ней подавтомат отмечен
специальным узлом.
Рисунок 2.10 – Главное окно приложения без подавтомата
В следующей версии сделана попытка упорядочить щелчки, соответственно элементам меню: file/exit, work, about (см.E.7):
agp1.fmsd 1.02.10
33
Рисунок 2.11 – Еще одна версия главного окна приложения
Следующая схема – дочернее окно представления табличных данных. Исходный код и пояснения к нему см. E.8.
Рисунок 2.12 – Использование кнопок панели инструментов в окне
табличного представления данных
Следующая схема – модальное окно быстрого поиска. Исходный
код достаточно простой, обсуждаться не будет. Пользователю де-
agp1.fmsd 1.02.10
34
монстрируется список записей. Он должен выбрать одну из них или
отказаться. Во время выбора в специальное поле (соответствующее
столбцу таблицы с записями) можно вводить текст, который используется для поиска нужной записи. Похожее окно представлено в [76,
стр.21]. Результат выбора используется при редактировании записи
или отношения один ко многим.
Рисунок 2.13 – Выбор записи
Следующая схема – редактирование отношения один-ко-многим.
Исходный код и пояснения к нему см. E.9. На панели отображается
главная запись (например, факультет), затем – верхний ряд кнопок
(Ok, Cancel), затем – список подчиненных записей (например, кафедры факультета), затем – нижний ряд кнопок (Add, Del). На форме
допускается редактирование главной записи, подобно диаграмме окна ввода данных, на рис. 2.8. Дополнительно, можно добавлять или
удалять подчиненные записи. Щелчок на кнопке Add приводит к появлению окна выбора записи (см. рис.2.13) и, возможное, добавление
новой записи в списке. Щелчок на кнопке Del приводит к удалению
из списка текущей подчиненной записи. Похожее окно представлено
в [76, стр.21].
agp1.fmsd 1.02.10
35
Рисунок 2.14 – редактирование отношения один-ко-многим
Замечание
Приведенные примеры UML - диаграмм состояний, в которых
описывались объекты .Net для создания пользовательского интерфейса, показывают, что при помощи понятия автомата можно достаточно адекватно описывать функциональность интерфейсов. Кроме того, важно, что автомат является математическим и, значит, формальным понятием и для него можно
формально ввести понятие наследования (см. [34, 25]).
2.1.5
SchemaSpy и схема реляционных связей БД
Единственным недостатком утилиты SchemaSpy является требование присутствия на компьютере Java - машины. Схемы, которые генерирует утилита (точнее, эти схемы генерирует одна из утилит пакета GraphViz) весьма качественные и хорошо читаются. Напрмер,
следующая схема 2.15 была использована в работе [27] для обсуждения картографической базы данных. Подробности об интерпретации
схемы реляционных связей баз данных см. в разделе [77, Схема реляционных связей].
agp1.fmsd 1.02.10
36
Рисунок 2.15 – Схема реляционных связей КБД
2.1.6
Форма Бэкуса — Наура (БНФ)
Естественным языком для описания требований к данным является формы Бекуса - Наура. Данный способ широко используется для
описания синтаксиса различных языков программирования, привы-
agp1.fmsd 1.02.10
37
чен для разработчиков ПО и может применяться в других, более простых случаях. В самом деле, текст программы на некотором языке
программирования является входными данными для соответствующего компилятора или интерпретатора. Хорошим примером изпользования БНФ является описание синтаксиса языка SQL на сайте
www.sqlite.org (см.https://www.sqlite.org/lang_select.html).
По адресу [1] можно скачать бесплатную утилиту для визуализации форм Бекуса - Наура в графической форме.
2.1.7
Doxygen и диаграммы классов
Doxygen [8] – это утилита создания документации для программ,
написанных на C++, C, Java, Objective-C, Python, IDL (Corba и
Microsoft) и некоторых версий PHP, C#, и D. Выходная документация представляет собой файлы в html-формате, в формате LaTex (в
частности, для дальнейшего создания pdf - файлов), rtf, справочного руководства в стиле Unix - man, справочного руководства в стиле
кросс платформенной библиотеки Qt, XML и так далее.
Даже, если не оформлять специальным образом исходные тексты,
Doxygen генерирует из них замечательные справочники программного интерфейса приложения. В выходной документ могут быть включены разделы с описанием используемых областей видимости, классов, файлов и их указатели на соответствующие разделы. В случае
использования пакета визуализации графов – Graphviz (см.[3], 2.1.3),
описание классов может сопровождаться симпатичными диаграммами. Примеры диаграмм достаточно сложного класса из реального
проекта представлен на рис. D.2.
Кирилизация Doxygen -а выполнена Александром Челпановым
(русский) и Алексем Ткаченко (Olexij Tkatchenko, украинский).
2.1.7.1 Создание отчетов в виде HTML страниц
Создадим справочник программиста в формате html по проекту
Hello, представленному в разделе A . Для этого необходимо выполнить следующие шаги
agp1.fmsd 1.02.10
38
• создать файл конфигурации Doxygen -а
doxygen -g hello
• получив файл конфигурации ./hello. (см. раздел B), являющийся текстовым файлом, задайте в нем следующие параметры:
–
–
–
–
–
–
–
PROJECT_NAME
=
hello
OUTPUT_DIRECTORY
= \_bld
каталог, где будет построена документация;
OUTPUT_LANGUAGE
= Russian
EXTRACT_ALL
= YES
по умолчанию, в документацию попадают только специально прокомментированные части кода. Здесь задано включение в документ всех классов, файлов и т.д., так как в
нашем проекте еще нет таких, специально прокомментированных частей кода.
INPUT
=
./csharp/
каталог, где находятся документируемый код;
FILE_PATTERNS
=
*.cs *.txt
документируемые файлы, из файлов .txt в отчет попадал
только один;
EXTRACT_STATIC
= YES
Этот параметр используется, чтобы включить в документ
статические члены файла;
• Постройте документацию командой
doxygen hello
Примечание
Подразумевается, что должна была получиться
следующая структура рабочего каталога
---- File:lslr.
agp1.fmsd 1.02.10
39
drwxrwxrwx
drwxrwxrwx
-rw-rw-rw-rw-rw-rw-
1 user
1 user
1 user
1 user
group
group
group
group
0 Apr 22 19:50 _bld
0 Apr 22 18:54 csharp
52381 Apr 21 16:23 hello
6328 Apr 22 19:53 lslr
csharp=:
total 11
-rwxrwxrwx
-rwxrwxrwx
-rw-rw-rw-rw-rw-rw-rw-rw-rw-
1 user
1 user
1 user
1 user
1 user
group
group
group
group
group
70 Apr 18 18:35 csc.bat
4608 Apr 22 18:54 hello.exe
500 Apr 22 18:51 lib.cs
2049 Apr 22 18:54 main.cs
342 Apr 22 18:48 main.txt
_bld=:
total 0
drwxrwxrwx
1 user
group
0 Apr 22 19:50 html
1 user
group
2202 Apr 22 19:50 annotated.html
1 user
group
1017 Apr 22 19:50 index.html
1 user
group
1758 Apr 22 19:50 tabs.css
_bld\html=:
total 145
-rw-rw-rw. . .
-rw-rw-rw. . .
-rw-rw-rw-
---- End Of File:lslr.
• откройте браузером файл ./ bld/html/index.html
Вполне вероятно, что Ваш браузер покажет вполне читабельную
страницу, похожую на страницу, представленную на рис. 2.16
agp1.fmsd 1.02.10
40
Рисунок 2.16 – Cтартовая страница html-документа по проекту
Hello
Кликнув на гиперссылку Классы, а затем, adm w::b увидим страницу 2.17
Рисунок 2.17 – Cтраница html-документа с описанием класса
adm w::b
agp1.fmsd 1.02.10
41
2.1.7.2 Диаграммы Doxygen-а и UML
Что бы включить в отчет графические диаграммы, нужно задать
еще некоторые параметры:
•
HAVE_DOT
= YES
Означает, что на компьютере установлен пакет визуализации
графов Graphviz [3] , и Doxygen будет пользоваться этим пакетом для генерации диаграмм. Много опций Doxygen имеет
смысл только тогда, когда используется Graphviz;
•
DOT_PATH
=
c:\bin\graphviz\bin
Задает путь к утилитам пакета визуализации графов;
•
HIDE_UNDOC_RELATIONS
= YES
Убирает из документа связи между недокументированными классами. В нашем примере классы a, b, c, и т.д. документированные, а класс int – не документирован;
•
CLASS_GRAPH
= YES
В описании класса появляется диаграмма наследования класса. На диаграмме отмечаются производные и базовые классы
текущего класса. В случае, если для диаграмм задан параметр
UML LOOK = NO то прямоугольники на этой диаграмме (см.
2.18) имеют следующее значение:
– Заполненный черный прямоугольник представляет структуру или класс, для которого создан граф.
– Прямоугольник с черной границей обозначает документированную структуру или класс.
– Прямоугольник с серой границей обозначает недокументированную структуру или класс.
– Прямоугольник с красной границей обозначает документированную структуру или класс, для которого не все отношения наследования/содержания показаны. Граф усечен, если он не поместился в указанных границах.
agp1.fmsd 1.02.10
42
Стрелки имеют следующее значение:
– Темно-синяя стрелка используется для изображения отношения открытого наследования между двумя классами.
– Темно-зеленая стрелка используется при защищенном наследовании.
– Темно-красная стрелка используется при закрытом наследовании.
– Фиолетовая стрелка используется, если класс содержится в другом классе или используется другим классом. Со
стрелкой указывается переменная, через которую доступен указываемый класс или структура.
– Желтая стрелка используется для связи подстановки шаблона и шаблона, на основе которого эта подстановка выполнена. С шаблоном указывается параметр подстановки.
и список классов потомков (наследуемые классы) и классов
предков (базовые классы).
•
COLLABORATION_GRAPH
= YES
Появляется граф связей класса. На диаграмме отмечаются производные, базовые и члены - объекты классы текущего класса.
Если выключен параметр HIDE UNDOC RELATIONS = NO
на диаграммах нашего проекта будут отображены все члены
класса включая поля dummy и dummy2;
•
UML_LOOK
= YES
любители UML могут использовать UML стиль диаграмм. Стрелки на UML диаграммах имеют следующий смысл (пример см.
приложение D):
1. стрелка на рис.2.21 означает наследование, стрелка направлена в сторону базового класса (в [47] такое отношение называется отношением есть ’is a’);
agp1.fmsd 1.02.10
43
2. стрелка на рис.2.22 означает наследование, ромбик расположен ближе к классу в котором объект второго класса
является полем(в [47] такое отношение называется отношением владеть ’has a’);
•
GRAPHICAL_HIERARCHY
= YES
Появляется граф с общей иерархией всех классов приложения
(см. рис. 2.19);
•
GENERATE_TREEVIEW
= YES
Приводит к появлению окна с деревом всех объектов проекта
как на рис. 2.20 ;
Рисунок 2.18 – Обозначения на диаграмме графа наследования
agp1.fmsd 1.02.10
Рисунок 2.19 – Построенная иерархия классов
Рисунок 2.20 – Дерево объектов проекта
44
agp1.fmsd 1.02.10
45
Рисунок 2.21 – Стрелка наследования
Рисунок 2.22 – Стрелка связи
2.1.7.3 Построение файла справки Микрософт
Для создания одного файла отчета с расширением .chm (компрессированный html) на компьютере должен быть установлен компилятор для файлов CHM – Microsoft HTML Help Workshop. После этого
в конфигурации Doxygen-а нужно задать следующие параметры:
•
GENERATE_HTMLHELP
= YES
опция задает создание CHM файла;
•
CHM_FILE
=
report.chm
название создаваемого CHM файла;
•
HHC_LOCATION
=
G:\bin
каталог, где находится компилятор файлов CHM (hhc.exe)
В случае, если chm файл не будет создан, не трудно создать его самостоятельно, откомпилировав файл index.hhp, следующей командой:
hhc.exe
index.hhp
Файл index.hhp должен находится в каталоге с построенным отчетом в виде HTML страниц. Компилятор hhc.exe в этом же каталоге
создаст файл report.chm.
Таким образом общий порядок построения отчета в виде компрессированного html выглядит следующим образом:
agp1.fmsd 1.02.10
46
Рисунок 2.23 – Потоки данных при построении файла справки
Таким образом, разработчик:
1. создает файлы приложения *.cs;
2. создает и редактирует файл конфигурации утилиты doxygen.exe;
3. при помощи утилиты doxygen.exe (и неявно при помощи утилиты dot.exe) создает html - файлы, схемы наследования и кооперации ( файлы *.png) и файл index.hhp;
4. при помощи hhc.exe создает файл справки.
Замечание
Microsoft HTML Help Workshop в настоящее время удален на
сайте Microsoft. По-видимому, утилита не совсем корректно работает с кодировкой utf-8. При использовании широкой кодировки навигационная (левая, с индексом) часть окна отображается не корректно.
agp1.fmsd 1.02.10
47
2.1.7.4 Улучшение текста отчета
Специальные комментарии, расположенные в коде программы попадают в документацию. Комментарии бывают короткие или подробные. Допускается не более одного короткого и одного детального комментария перед каждом документируемым элементом (файл,
класс, переменная, функция, перечисление и т.д.) проекта. Обьект
файл представляет собой исключение и будет обсужден позже. Есть
много разных возможностей для коротких и подробных комментариев, остановимся на двух
• дополнительный символ слэш – /// создает короткий комментарией;
• дополнительный символ звездочка – /** создает подробный коментарий.
Следующий код
/// Глобальные переменные приложения 1
public class
gVars
/**
Эти переменные могут использоваться в каждом классе или каждой функции
приложения.
*/
приводит к изменениях в документе, показанных на рис. 2.24 и 2.25 .
Напоминаем, что комментарий должен быть перед комментируемым
элементом проекта, по крайней мере, в данном случае, перед открывающей скобкой класса. Символ < может изменить это правило.
public const string
public const string
path = "./var";
nm
= "adm_w.log";
///< каталог временных файлов.
Символ больше < говорит Doxygen , что комментарий относится не
к nm, а к path.
agp1.fmsd 1.02.10
48
Рисунок 2.24 – Пример короткого комментария
Рисунок 2.25 – Пример подробного комментария
2.1.7.5 Дополнительные команды
Существует набор специальных команд для улучшения читабель-
agp1.fmsd 1.02.10
49
ности текста и позволяющий держать комментарии в дополнительных файлах.
В частности, команда ∖file используется для комментирования
файла, как показано в файле lib.cs:
/** \file
\brief файл с библиотекой
*/
Мы не будем останавливаться на всех командах, а приведем пример c
• использованием списков (элемент списка отмечается символом
-);
• комментированием файла ( команда ∖file) внутри и вне файла;
• команды автор (∖author);
• команды дата (∖date);
• команды замечание (∖note);
• команды короткий комментарий (∖brief);
• команды новый параграф (∖par);
В каталог ./csharp поместим файл main.txt со следующим содержанием:
---- File:./src/csharp/main.txt
/**
\file main.cs
\brief главный файл приложения
очень подробное описание файла main.cs
\author Вася Пупкин
\date 2006
\note
agp1.fmsd 1.02.10
50
это приложение было разработано для рассылки hDrummer-а,
члена sql.ru с 2002 года.
\par
Цель проекта заключалась в
- демонстрации возможностей Doxygen-а;
- введению в Doxygen.
*/
---- End Of File:./src/csharp/main.txt
Изменим параметр файла конфигурации Doxygen
FILE_PATTERNS
=
main.txt *.cs
Тогда в выходном документе появятся изменения, показанные на
рис. 2.26.
Более сложный пример форматирования отчета можно посмотреть в приложении C.
agp1.fmsd 1.02.10
51
Рисунок 2.26 – Пример документирования файла main.cs
2.2
Система компьютерной верстки LaTex
LaTex - система компьютерной верстки, первоначально разработанная Дональдом Кнутом. Точнее он разработал Tex, а потом к нему
добавили множество макрорасширений, облегчающих задачу генерации документа и назвали её LaTex . Наиболее популярная вер-
agp1.fmsd 1.02.10
52
сия LaTex-а сейчас – TexLive (см. http://www.tug.org/texlive/).
Именно им строился текущий документ, при помощи утилиты pdflatex.exe.
Система LaTex - достаточно стабильная, эксплуатируется много лет,
можно быть уверенным, что использовать его удастся до пенсии без
особых изменений. Файлы в формате LaTex представляет собой
текстовый файл в котором, кроме требуемого текста, находятся команды настроек, команды для разметки документа и специальные
символы. Документ делится на преамбулу и тело документа. Для
начального освоения LaTex достаточно читать монографию Львовского [84].
Замечание
Такой генератор документации как doxygen (см. [69]) совместим с LaTex-ом и может генерировать документацию в его
формате.
2.2.1
Преамбула и структурные части документа
Преамбула – это набор команд для настройки документа. Для начала можно взять преамбулу из раздела 4.1. Преамбула начинается
командой \documentclass (см.ниже) и должна содержать команды
\begin{document} и \end{document} между которыми содержится
текст документа. Собственно тело документа должно находиться в
отдельном файле !!wrong command: text0.tex, в каталоге, рядом с
преамбулой.!!Включается тело документа в преамбулу командой
\begin{document}
\input {.text0}
\end{document}
Команду \input можно использовать в теле документа несколько
раз. При этом весь документ будет строится из нескольких файлов.
Кириллица (в частности, подразумеваются слова ’Содержание’, ’Глава’ и т.д.) подключается командой
\usepackage[russian]{babel}
или
agp1.fmsd 1.02.10
53
\usepackage[english,ukrainian]{babel}
Очень влияет для отображения рисунков (размер и расположение
в тексте документа):
\usepackage{float}
Кодировка входного файла:
\usepackage[cp1251]{inputenc}
Класс документа задается командой:
• статья
\documentclass[a4paper,oneside]{article}
• отчет:
\documentclass[a4paper,oneside]{report}
• книга:
\documentclass[a4paper,oneside]{book}
• диплом (тут указан 14 кегль):
\documentclass[a4paper,oneside,14pt]{extreport}
Поля – левое, верхнее, правое, нижнее (далее колонтитулы и расстояние до номера страницы):
\setmarginsrb{2.5cm}{2cm}{1.5cm}{2cm}{0pt}{0mm}{0pt}{13mm}
В случае класса документа article (статья), деление документа на
отдельные части (которые заносятся в оглавление, глубиной 1, 2, 3
и 4) выполняется командами:
agp1.fmsd 1.02.10
54
\section{ ФОРМАЛЬНЫЕ СПЕЦИФИКАЦИИ И РАЗРАБОТКА ПО}
. . .
\subsection{ Система компьютерной верстки LaTex}
. . .
\subsubsection{ Преамбула}
. . .
\paragraph{ Делегирующий конструктор}
~
\medskip
Документы класса book или report делятся на главы:
\chapter {НАЗВАНИЕ}
LaTex по англосаксонской традиции не выделяет заголовок параграфа на отдельной строке, поэтому после команды paragraph нужно
добавить символ пробела (тильда ~) и команду пропуска строки,
Команда setcounter задает счетчики глубины нумерации разделов и
занесения их в оглавление.
\setcounter{secnumdepth}{4}
\setcounter{tocdepth}{4}
Собственно содержание выводится командой:
\tableofcontents
В случае использования титульной страницы документа, в ней,
по меньшей мере, должны быть использованы команды \title и
\author. Файл с титульной страницей текущего документа:
---- File:title.tex
\title{Документирование процесса разработки ПО\\ {\small}}
\author{А.Г.Пискунов }
---- End Of File:title.tex
При это придется усложнить текст документа:
agp1.fmsd 1.02.10
\begin{document}
\input {title}
\maketitle
\thispagestyle{empty}
\newpage
\setcounter{page}{2}
\pagestyle{myheadings}
\input {.text0}
55
%% прочитать титульную страницу
%% вывести её в документ
%% отменить нумерацию на ней
%% перейти на новую страницу
%% счетчик страниц установить в 2
%% восстановить нумерацию страниц
Иногда требуется отменить значение специальных символов или
команд разметки. Тогда применяется команда буквального воспроизведения теста: \verb+блаблабла+, где на месте символа + может
быть использован любой символ (главное – один и тот же, в одной
команде), а на месте текста ’блаблабла’ располагается тест, который
требуется буквально воспроизвести в построенном документе.
2.2.2
Предметный указатель
Предметный указатель – список терминов вместе со страницами, на
которых они упоминались. Для его использования требуется:
• в преамбуле подключить расширения makeidx и попросить его
создание:
\usepackage{makeidx}
\makeindex
• термин заносится в список терминов командой:
\index{преамбула}
теперь слово ’преамбула’ появится в предметном указателе;
• в случае класса документа extarticle или article, перед выводом
списка литературы вставить команды:
\printindex
\addcontentsline{toc}{section}{ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ}
agp1.fmsd 1.02.10
56
• в случае класса документа extreport, команды ∖printindex и
∖addcontentsline надо вставлять в обратном порядке и добавить
команду ∖phantomsection:
\phantomsection
\addcontentsline{toc}{chapter}{ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ}
\printindex
Собственно, сам предметный указатель строится утилитой makeindex.exe,
которую нужно выполнить между несколькими применениями pdflatex.exe.
В [51] раздел ’Предметный указатель’ не упоминается совсем. В рекомендациях https://odeku.edu.ua/oformlennya-rukopysiv-ta-posylan/
этот роздел размещают после разделов ’Литература’ и ’Глоссарий’,
перед приложениями.
Подробности см. по адресу: http://mydebianblog.blogspot.com/
2008/03/index-in-latex-howto.html
2.2.3
Библиография
База ссылок для LaTex-а представляет собой файл приблизительно
следующей структуры:
---- File:./etc/example.bib
@MISC{ ZED:Spivey,
AUTHOR = "Spivey, J. M.",
TITLE = "The Z Notation: A Reference Manual.",
NOTE = "Prentice Hall International Series in Computer Science, 2nd edition, 1992."
}
@MISC{ ZTC,
AUTHOR = "Jia, X.",
TITLE = "ZTC: A Type Checker for Z Notation. User’s Guide.",
NOTE = "Version 2.03, August 1998. Division of Software Engineering, School of Computer Science
}
@MISC{ WayOfZ,
AUTHOR = "Jacky, J.",
TITLE = "The Way of Z: Practical Programming with formal Methods.",
NOTE = "Cambridge University Press, 1997."
}
agp1.fmsd 1.02.10
57
.
---- End Of File:./etc/example.bib
который должен располагаться желательно в одном каталоге (в случае MikTex-а его можно располагать в другом каталоге) с файлами преамбулы и документа. В данном случае слова WayOfZ, ZTC
и ZED:Spivey являются ключами, которые используются в команде
цитирования LaTex-а (команда \cite)):
\cite{ZTC}
\cite[стр.25]{ZED:Spivey}
\cite[’When are formal methods useful?’]{ZED:Spivey}
В случае файла текущего примера example.bib в тело документа требуется добавить команды:
\bibliographystyle{plain}
%\bibliographystyle{unsrt} %%
\bibliography{example}
\addcontentsline{toc}{section}{СПИСОК ЛИТЕРАТУРЫ~~~~.~~~~.~~~~~.~~~~~.~~~~~.~~~~~.~~~~~.~~~~~}
Причем файлов со ссылками (в данном примере это файл example.bib)
может быть несколько. В команде \bibliography их можно добавлять через запятую. Следующая команда \bibliographystyle управляет процессом подготовки раздела ’Список литературы’. При стиле
plain список литературы сортируется по алфавиту, причем сначала
идут английские буквы, за ними – буквы кириллицы. При стиле unsrt
список литературы сортируется в порядке упоминания в документе.
Первая, упомянутая в документе, ссылка на литературу (цитирование, команда \cite) оказывается первой в списке литературы и так
далее.
Кроме того, между вызовами LaTex-а требуется использовать
утилиту bibtex.exe. Первый раз вызывается pdflatex.exe, затем makeindex.exe,
затем bibtex.exe и два запуска pdflatex.exe. Подробности см. по адресу: https://ru.wikipedia.org/wiki/BibTeX. Например, текущей
документ строился следующим командным файлом:
agp1.fmsd 1.02.10
---- File:./mkpdf.cmd
SET GOAL=text
echo on
call ..\..\params.%COMPUTERNAME%.cmd
echo off
rem SET BIB=..\..\bibDB
SET LATEX=%P%\pdflatex.exe
SET MKIDX=%P%\makeindex.exe
SET BIBTEX=%P%\bibtex.exe
SET PAR=doxygen;class=article;vsize=2;
echo on
copy tmain.tex .%GOAL%.tex
rem препроцессор mkTex
if %1. == 0.
goto one
%MKT% %PAR% <%GOAL%0.rio > .%GOAL%0.tex
%MKT% %PAR% < %GOAL%0FSS.rio > .%GOAL%0FSS.tex
%MKT% %PAR% <%GOAL%00.rio > .%GOAL%00.tex
%MKT% %PAR% <%GOAL%01.rio > .%GOAL%01.tex
%MKT% %PAR% <%GOAL%02.rio > .%GOAL%02.tex
%MKT% %PAR% <%GOAL%0K.rio > .%GOAL%0K.tex
%MKT% %PAR% <%GOAL%03.rio > .%GOAL%03.tex
%MKT% %PAR% <%GOAL%030.rio > .%GOAL%030.tex
%MKT% %PAR% <%GOAL%031.rio > .%GOAL%031.tex
%MKT% %PAR% <%GOAL%032.rio > .%GOAL%032.tex
%MKT% %PAR% <dgIntro.rio > .dgIntro.tex
%MKT% %PAR% <%GOAL%04.rio > .%GOAL%04.tex
%MKT% %PAR% <%GOAL%05.rio > .%GOAL%05.tex
%MKT% %PAR% <%GOAL%0Ex.rio > .%GOAL%0Ex.tex
%MKT% %PAR% <%GOAL%z.rio > .%GOAL%z.tex
%MKT% %PAR% <introZ2.rio > .introZ2.tex
%MKT% %PAR% <doxyCol.rio > .doxyCol.tex
%MKT% %PAR% <stateMachine.rio > .stateMachine.tex
rem %MKT% %PAR% <textSPI.rio > .textSPI.tex
.rio
%MKT% %PAR% <%GOAL%SPI.rio > .%GOAL%SPI.tex
%MKT% %PAR% <%GOAL%Pr.rio > .%GOAL%Pr.tex
%MKT% %PAR% <%GOAL%PrQ.rio > .%GOAL%PrQ.tex
rem %MKT% %PAR% <%GOAL%Pr2.rio > .%GOAL%Pr2.tex
%MKT% %PAR% <%GOAL%Hrb.rio > .%GOAL%Hrb.tex
58
agp1.fmsd 1.02.10
59
%MKT% %PAR% <adm_aDF1.rio > .adm_aDF1.tex
%MKT% %PAR% <gls.rio > .gls.tex
if %1. == 1.
goto one
%LATEX% -interaction=batchmode
.%GOAL%.tex
%MKIDX%
>.makeindex.log .%GOAL%.idx -o .%GOAL%.ind
%BIBTEX%
.%GOAL%
1>.%GOAL%.bib.log
%LATEX% -interaction=batchmode
.%GOAL%.tex
:one
%LATEX% -interaction=batchmode
.%GOAL%.tex
exit
---- End Of File:./mkpdf.cmd
Некоторые сервисы для хранения документов, такие как журналы или ResearchGate.net, позволяют скачать цитирование выбранного документа. Например, на ResearchGate.net цитирование можно
взять следующим образом:
• нажать кнопку ’Download citation’:
agp1.fmsd 1.02.10
60
Рисунок 2.27 – Подсказка cmd
• затем выбрать стиль BibTex
Рисунок 2.28 – Подсказка cmd
• в полученном файле первую строчку
agp1.fmsd 1.02.10
61
@unknow{unknow,
@article{AGP:CLSDSGN,
, где ’AGP:CLSDSGN’ – уникальный идентификатор записи в
файлах списков цитирования.
Обсуждение особенностей LaTex-а, связанных с удовлетворением требований госстандартов для научно- технических отчетов см. в
[30].
2.3
Проектирование ПО и LaTex
2.3.1
Проектирование и тестирование ПО
В методе проектирования по контракту Б.Мейера (см. [60]) и в других методах формальной разработки (см. 2.5.9) из большого объема
полезной для разработчиков информации, можно выделить следующие моменты: при проектировании ПО желательно добиться расширяемости ПО в мало предсказуемом будущем, повторного использования разработанных частей ПО и надежной их работы.
Для достижения этих целей (и еще такой, как экономии усилий
проектировщика ПО и кодера) используется метод проектирования
сверху - вниз. Сначала описываются требования к планируемому
программному обеспечению, эти требования используются для разделения (декомпозиция) всего будущего ПО (пусть условно называется система) на некоторые функциональные части (условно называется подсистема). Далее описываются и уточняются требования к
этим частям (подсистемам). В свою очередь, подсистемы опять делятся на части (например, классы или библиотеки функций). Так
продолжается до тех пор, пока полученные маленькие части ПО
удается описать небольшими функциями (скажем до 60 строчек) на
языке программирования, который выбран для разработки ПО. Такая логически связанная между собой группа функций, переменных
и/или классов, предназначенных для решения какой-то конкретной
agp1.fmsd 1.02.10
62
задачи и позволяющая отдельную компиляцию будут далее называться модулем или единицей компиляции. Эта часть работ по созданию ПО называется разработкой архитектуры ПО. Не слишком
громоздкий пример разработки системы управления портом от группы авторов формального метода разработки RAISE представлен в
разделе 2.5.9. Пока можно отметить, что разработка порта начинается с анализа требований к будущему ПО.
Примеры требований к ПО можно посмотреть в [86, стр.53-60].
Более подробное обсуждение вопросов проектирования ПО можно
найти в 4-й и 5-й главах нестареющий монографии Г.Майерса (см.[48]).
В более крупных проектах, количество готовых к кодированию
модулей (то есть, групп функций, переменных и/или классов), которые получаются в результате работы над архитектурой, становится
большим. Например, больше четырех. И, естественно, желательно
добиваться наведения порядка в этих группах. Модули должны быть
по возможности не зависимы друг от друга и иерархически упорядочены. Хорошая архитектура должна напоминать одну из следующих
схем ([48, гл.5]):
Рисунок 2.29 – Примеры идеальной архитектуры ПО
где линия из верхнего уровня абстракции в нижний означает, что
в методе или функции верхнего уровня есть обращение к классу, методу или функции нижнего. Несколько модулей расположенных в
agp1.fmsd 1.02.10
63
одной горизонтальной группе может называться уровнем абстракции. Схемы на рис. 2.29, в общем, иллюстрируют выражение ’проектирование ПО сверху-вниз’.
Замечание
Примеры архитектуры, спроектированной согласно рис. 2.29,
можно посмотреть в разделе 4.2.
В качестве дополнения к такому проектированию самым экономным способом разработки (кодирования классов, функций и их
тестирования) оказывается метод кодирования и тестирования модулей снизу - вверх (восходящее тестирование (bottom-up testing),
[86, стр.103]). Сначала пишутся мелкие функции и/или классы (полученные на последнем этапе проектирования), затем модули, использующие уже написанные функции (и/или классов) и так далее,
до завершения разработки всего ПО. При этом, разрабатывать программы из следующего уровня абстракции нужно после разработки,
тестирования, отладки и документирования программ предыдущего уровня. Вследствие того, что методы и/или функции следующего
уровня используют методы и/или функции предыдущего, то придется тратить некоторые усилия разработчика для создания дополнительных (тестирующих) методов и/или функций, которые будут
пользоваться разрабатываемыми классами и/или функциями текущего уровня абстракции. Эти дополнительные тестирующие методы
и/или функции имеют название драйверы тестов. Таким образом,
на завершающих этапах разработки ПО классы и функции нижнего
уровня абстракции оказываются тщательно протестированы, аккуратно документированы и не должны вызывать никаких сомнений в
корректности своей работы.
Рассмотренный порядок выполнения работ естественным образом вписывается в V-образную модель разработки ПО (см. [86, стр.23]
или https://ru.wikipedia.org/wiki/V-Model):
agp1.fmsd 1.02.10
64
Рисунок 2.30 – V-образная модель разработки ПО
Замечание
Тестирование ПО из нижних уровней абстракции будет называться модульным тестированием. Тестирование ПО на заключительных стадиях разработки (то есть, верхних уровней абстракции) – системным или комплексным тестированием.
Дополнительно нужно подчеркнуть важность наличия требований к всему разрабатываемому ПО вообще и каждому отдельному
модулю в частности. бесполезно говорить о тестировании любых частей разрабатываемого ПО при отсутствии требований к этому разрабатываемому ПО. Таким образом, нужно рассмотреть способы, которыми эти требования могут быть записаны. В первую очередь,
будут интересовать требования к входным и выходным данным, отдельным функциям и/или классам.
agp1.fmsd 1.02.10
2.3.2
65
Требования к ПО
Святослав Куликов дает такое определение (см.[87, Что такое требование]): Требование (requirement) – описание того, какие функции
и с соблюдением каких условий должно выполнять приложение в
процессе решения полезной для пользователя задачи.
В трактовке International Software Testing Qualifications Board (см.[10]):
требование (requirement) – условия или возможности, необходимые
пользователю для решения определенных задач или достижения определенных целей, которые должны быть достигнуты для выполнения контракта, стандартов, спецификации, или других формальных
документов. Такие определения термина требование существенно
отличается от аналогичного определения Международной организации по стандартам (см.F.1). В них включены и пользователь, и
полезные для пользователя задачи. А в определение International
Software Testing Qualifications Board добавлены упоминания о стандартах, спецификациях и других документов. и это, естественно,
подводит к мысли о необходимости собирать и описывать требования
в спецификациях к ПО.
В этом же должен убеждать словарь Международной организации по стандартам (см.[14, 4.1387]): технические требования (specification):
Документ, устанавливающий законченным, точным, поддающимся
проверке способом требования к системе или компоненту системы,
их проект, поведение или характеристики.
Ключевым моментом в этом определении является возможность
точной проверки удовлетворяет ли ПО требованию или нет. При отсутствии возможности таковой проверки требование становится не
требованием, а пожеланием.
Итак, требования должны содержать:
• пояснение зачем разрабатывается данное ПО;
• задачи, которые пользователь может выполнять с помощью
данного ПО;
agp1.fmsd 1.02.10
66
• особенности, принятых в предметной области процессов, ограничений и правил;
• описание ключевых для данного ПО показателей, не связанных
с функциональностью, но важными для достижения целей создания ПО;
• описание поведения ПО;
• описание свойств ПО, которыми оно должно обладать при реализации своего поведения;
• список ограничений, влияющих на выбор способов и средств
реализации ПО;
• особенности взаимодействия ПО с другим ПО;
• особенности данных, которыми пользуется ПО.
При этом качественное требование должно быть
• полным и законченным, с точки зрения представления в нём
всей необходимой информации;
• атомарным, то есть, не может быть разбито на отдельные подтребования без потери свойства полноты;
• не противоречивым ни с самим собой, ни с другими требованиям и документами;
• недвусмысленным, то есть, допускать только однозначное толкование;
• технически реализуемым в рамках бюджета и сроков разработки ;
• обязательным для выполнения (если не очень обязательным,
то с пометкой важности);
• корректным и проверяемым.
agp1.fmsd 1.02.10
2.3.3
67
Абстрактные типы данных
Для документирования требований к классам (как естественному,
наименьшему структурному элементу в рамках ООП) естественно
использовать абстрактные типы данных. Они позволяют описывать
будущее ПО максимально абстрактным образом, в частности, без
явно задаваемых на ранних этапах проектирования, алгоритмов и
структур данных.
Шутка Дейкстры
Абстрактные типы данных являются прекрасной теорией, целью которой является описание стеков.
Еще раз, при проектировании ПО требуется добиваться:
• однозначного описания задачи, чтобы избежать различного толкования описания будущими кодировщиками, что влечет необходимость иметь формальный однозначный язык спецификаций и/или необходимость пользоваться математическими терминами;
• достаточного полного описания, тем или иным образом отвечающего на поставленную задачу: что должно уметь делать
разрабатываемое ПО;
• не слишком подробного описания. Текст описания классов и
функций должен быть гораздо короче текста будущих программ, иначе его не будут читать. Кроме того, текст описания
не должен навязывать кодировщикам решений, которые можно
будет принять позже. Непредсказуемые (и не предусмотренные
в спецификации) изменения в требованиях к разрабатываемому ПО – повлекут переделку не только текстов программ, но и
переделку спецификаций, что увеличивает накладные расходы
на разработку.
Именно этим занимались математики когда строили формальное описание таких алгебраических систем, как кольцо целых чисел
agp1.fmsd 1.02.10
68
(см.[62, стр.95]) и поле вещественных чисел (см.[62, стр.102]). Правда, кроме доказательства полноты описываемых систем, математики доказывали, что абстрактное описание влечет единственность и
непротиворечивость (см.[62, стр.100]) описываемой системы (существует только одно кольцо целых чисел и только одно поле вещественных чисел).
Описание абстрактного типа данных у Б.Мейера (равно как у
авторов The RAISE Language Group) включает четыре раздела:
• обозначения (имена) множеств, которые будут удовлетворять
требованиям текущего абстрактного типа данных, без какойлибо конкретизации. Эти обозначения будут использоваться в
сигнатурах функций, предусловиях и аксиомах. Будет называться домен абстрактного типа или не определяемым типом.
Это множество стеков STACK[G] и элементов стеков G в [60,
стр.193], множество целых Z в [62, стр.95], множества кораблей,
пристаней и портов Ship, Berth, Harbor в [13, стр.13]. В методе
разработки RAISE (2.5.9.4) такие обозначения множеств имеют специальное название – сорт и называются типом интереса
спецификации;
• Сигнатуры функций, которые будут определены на описываемых множествах. В объектно - ориентированных языках такие
функции - операции реализуются как методы. В [60, стр.197]
– это функции put, remove, item, empty и new, в [62, стр.95] –
это функции сложения и умножения, в [13, стр.15] – это функции arrives – прибыть в порт, docks – причалить; Функции могут быть частичными, то есть, неопределенными на некоторых
значениях из определяемых типов (такой функцией является
функция деления, она не определена для деления на 0).
• аксиомы, которым будут удовлетворять функции абстрактного
типа. Аксиомы этого раздела делятся на две группы: инварианты и постусловия. Инварианты – условия, которые выполняются всегда на протяжении всей работы приложения. По-
agp1.fmsd 1.02.10
69
стусловия выполнения функции – условия, которые выполняются, после применения соответствующей функции. Постусловия позволяет задавать функции в неявной форме, то есть, без
описания алгоритма. Например, требование к функции извлечения квадратного корня можно записать следующим образом:
sqrt : X ; X ∧ ∀ x ∈ X ∙ x > 0 ⇒ sqrt(x) · sqrt(x) = x
• предусловия – условия которые явно описывают ситуации, при
которых можно применять соответствующие функции. Например, они задают области определения частичных функций. См.
[60, стр.206], [62, стр.95], [13, 3.6.1.2 Функции waiting, docks]
Говорят, что такая спецификация написана в абстрактном аппликативном стиле. Слово абстрактный используется в связи с наличием
не определяемого типа, который используется в качестве домена абстрактного типа и его функций. Слово аппликативный (applicative),
видимо, используется в связи с требованиями в виде применения
(apply) функций.
Спецификация абстрактного типа, заданная в такой форме, будет
называться контрактом.
2.3.3.1 Очереди и стеки
Рассмотрим следующее частичное описание, для полного описания
кроме указанного ниже, нужно еще описывать функции и аксиомы.
Пусть T – тип, S[T] – тип последовательность элементов типа T,
пусть на них заданы функции
• pop : S[T] → S[T] – удаляет элемент из последовательности
S[T];
• top : S[T] → T – показывает элемент из последовательности
S[T], который будет удаляться функцией pop;
• push : S[T] × T → S[T] – добавляет один элемент в последовательность S[T] .
agp1.fmsd 1.02.10
70
Тогда требования к функциям задаются следующим образом (упражнение У6.10 [60, стр.241]):
• в случае стека: ∀ t ∈ T, s ∈ S[T] ∙ top(push(s, t)) = t – тот
элемент, который втолкнули в последовательность, будет кандидатом на выталкивание;
• в случае очереди: ∀ t ∈ T, s ∈ S[T] ∙ top(push(s, t)) = top(s) –
чтобы не добавили в последовательность кандидат на удаление
не меняется, кроме того, в этом случае последовательность s
должна быть не пустая. Это условие должно быть записано в
разделе предусловия. Естественно, нельзя посмотреть элемент
в пустой последовательности. Это и означает, что функция top
– частичная.
• в случае стека: ∀ t ∈ T, s ∈ S[T] ∙ pop(push(s, t)) = s – два
последовательных применения функций добавить и удалить не
меняют последовательность;
• в случае очереди: ∀ t ∈ T, s ∈ S[T]∙pop(push(s, t)) = push(pop(s), t)
– порядок двух последовательных применений функций удалить и добавить не имеет значения, в результате получится та
же последовательность.
Замечание
В случае перехода к реализации типа, аксиомы принято называть постусловиями.
2.3.3.2 Кольцо целых – создание типа и математика
В качестве примера, который опровергает шутку Дейкстры, рассмотрим частичное описание кольца целых чисел. Пусть N – некоторое множество, функции:
• sum : N × N → N – функция сложения двух целых;
• mult : N × N → N – функция умножения двух целых;
agp1.fmsd 1.02.10
71
Кроме всего прочего, эти функции описываются следующими аксиомами:
• ∀ a, b, c ∈ N ∙ mult(sum(a, b), c) = sum(mult(a, c), mult(b, c))
– дистрибутивность функций сложения и умножения (в более
привычном виде дистрибутивность записывается как (a + b) ·
c = a · c + b · c);
• ∀ a, b ∈ N ∙ sum(a, b) = sum(b, a) – коммутативность сложения;
• ∀ a, b ∈ N ∙ mult(a, b) = mult(b, a) – коммутативность умножения;
Этот пример, как бы намекает, что проектировщики ПО занимаются той же работой, которой занимались математики при разработке алгебры и матанализа в свое время (а именно – абстрагированием:
выделением из большого количества непонятного некоторое количество понятного и его (понятного) формального описания). Поэтому,
проектировщикам ПО хорошо бы представлять как математики делали свою работу.
2.3.4
Математический режим LaTex-а
Все сказанное выше должно было подвести к мысли об умении использования математики, математических обозначений и, следовательно, математического режима LaTex-а (дополнительный справочник см. [43]). Он может использоваться тремя способами:
• текст формулы набирается между двумя символами доллара $
– тогда эта формула не будет выноситься на отдельную строку:
a = b + c;
• текст формулы располагают между прямоугольными скобками
с лидирующим бакслешем:
\[ a = b + c \]
agp1.fmsd 1.02.10
72
– так называемая выключенная формула (то есть, такая которая располагается на отдельной строке):
a=b+c
• в случае необходимости автоматической нумерации формул используется окружение equation:
\begin{equation} a = b + c
\label{f:1}
а это ссылка на формулу -- \ref{f:1}.
\end{equation}
формула выглядит следующим образом:
a=b+c
(2.1)
а это ссылка на формулу – 2.1. Если документ имеет класс
отчет или книга (report или book), то номера формул будут
состоять из двух чисел, первое совпадает с номером текущей
главы.
• для много строчных формул используется окружение cases:
\begin{cases}
0 \\
e^{-1/x}
\end{cases}
{︃
0
формула выглядит следующим образом:
e−1/x
Математический режим LaTex-а обладает следующими особенностями:
• промежутки между символами выбираются из логики формулы, поэтому пробелы просто игнорируются. При необходимости можно использовать символ тильда ~ для вывода маленького пробела в математическом режиме;
agp1.fmsd 1.02.10
73
• нельзя использовать пустые строки;
• в математическом режиме кириллица набирается при помощи
команды \text{. . .}(иначе кириллица исчезнет), при подключенном пакете amsmath. Например, текст
$ a = b ~ привет мир \text{прощай мир } + c$;
выглядит как: a = b прощай мир + c;
agp1.fmsd 1.02.10
74
2.3.4.1 Математические символы LaTex-а
Некоторые, часто используемые математические символы LaTex-а
собраны в следующих таблицах:
Таблица 2.1 – Таблица символов LaTex-а (начало)
символ
∪
∩
∖
⊂
⊆
∈
̸
∈
∋
∅
∞
×
P
↔
→
⇀
˓→
как набрать
\cup
\cap
\setminus
\subset
\subseteq
\in
\notin
\ni
\emptyset
\einfty
\times
\mathbb{P}
\leftrightarrow
\to
\rightharpoonup
\hookrightarrow
↦→
[
]
{
}
·∑︀
\mapsto
\lbrack
\rbrack
\lbrace
\rbrace
\cdot
\sum
\prime
′
что значит
пакет
объединение
пересечение
разность множеств
включается строго
включается
принадлежит
не принадлежит
принадлежит
пустое множество
бесконечность
прямое произведение
множество всех подмножеств amssymb
отношение
всюду определенная функция
частичная функция
еще одна версия
частичной функции
отображение элементов
скобка
скобка
скобка
скобка
умножение
сумма
штрих производной
agp1.fmsd 1.02.10
75
Таблица 2.2 – Таблица символов LaTex-а (продолжение)
символ
∃
∀
∙
⇒
⇔
∨
∧
¬
...
≤
≥
<
>
̸
=
как набрать
\exists
\forall
\bullet
\Rightarrow
\Leftrightarrow
\lor
\land
\lnot
\dots
\le
\ge
\textless
\textgreater
\ne
что значит
пакет
квантор существования
квантор всеобщности
элемент предиката
следует
логическая эквивалентность
логическое ИЛИ
логическое И
логическое НЕТ
многоточие
не больше
не меньше
строго меньше
строго больше
не равно
Замечание
Стрелки для частично определенных функций см. https://
en.wikipedia.org/wiki/Partial_function.
Изменить шрифт можно при помощи символа mathcall, например: \mathcal{ABC} - 𝒜ℬ𝒞. Далее, часто нужны
z1
• верхние индексы: x^{y^{z1}} - xy ;
• нижние индексы: x_{y_{z1}} - xyz1 ;
• совместное использование индексов: {x_{12}}^3} - x12 3 ;
• символ штриха: f^\prime - f ′ .
Символы фигурных скобок используются для группирования индексов.
agp1.fmsd 1.02.10
76
Замечание
Совершенно опущены не очень нужные сейчас вопросы создания дробей (\frac), сложных сумм и сложных интергалов. По
этим вопросам можно заглянуть на следующую ссылку: https:
//ru.wikibooks.org/wiki/%D0%9C%D0%B0%D1%82%D0%B5%D0%BC%
D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5_%D1%
84%D0%BE%D1%80%D0%BC%D1%83%D0%BB%D1%8B_%D0%B2_LaTeX.
Для отчетов программистов потребуется еще одна возможность
LaTex-а , а именно – подключение к тексту отчета текстов программ
в неизменном виде. Для этого можно использовать пакет verbatim
и команду для буквального воспроизведения содержимого файлов:
\verbatiminput. Команда иногда игнорирует символ широкого пробела. Как альтернативу можно использовать более сложный пакет
listings, который позволяет подстраивать текст под используемый
язык программирования, команда: \lstinputlisting (подробности
см.https://www.overleaf.com/learn/latex/Code_listing#Importing_
code_from_a_file).
Вообще говоря, ничего не мешает теперь писать спецификации на
языке LaTex-а и помещать такие спецификации в качестве комментариев в код программы. Но, в общем, LaTex – не слишком прост и
никто не гарантирует отсутствие ошибок в спецификации. Поэтому
хотелось бы иметь возможность хоть какой-то проверки текста, которую обычно предлагают компиляторы. Такие возможности предоставляют языки формальных спецификаций и утилиты проверки
правописания, специально для них разработанные. В текущем документе будут обсуждаться два таких языка (RSL и Z) и две утилиты
проверки правописания.
2.4
Проектирование по контракту
Общие рассуждения о требованиях к ПО см. в 2.3.2.
agp1.fmsd 1.02.10
2.4.1
77
Требования к модулям и связям между ними
Материал нескольких подразделов взят из [48]. В разделе рассматриваются требования к модулям и связям между ними в смысле не
специальных требований к функциональности (например, посчитать
зарплату сотрудникам компании), а общих требований к разрабатываемому ПО. Следующий список (см. [60]) содержит обычные и
общепринятые требования:
• корректность (correctness) – способность ПО выполнять задачи
точно в соответствии со спецификацией.
• устойчивость (robustness) – способность ПО реагировать на аварийные ситуации.
• расширяемость (extendibility) – это легкость адаптации ПО к
изменениям спецификации.
• повторное использование (reusability) способность элементов ПО
служить для построения разных систем.
• совместимость (compatibility) это легкость сочетания одних элементов ПО с другими.
• эффективность (efficiency) - способность ПО как можно меньше зависеть от ресурсов оборудования: мощности центрального
процессора, памяти или пропускной способности
Эти требования очень напоминают просто благие пожеланиями за
все хорошее против всего плохого. Различные авторы их формулируют начиная с времен Fortran-IV, а может и раньше. Перейдем к
рассмотрению требований к ПО из(см.[48, Проектирование структуры программы]), которые позволяют по формальным признакам
принимать конкретные решения при проектировании ПО.
Предположим, перед разработкой некоторого приложения app.exe,
шаг проектирования архитектуры не выполнялся вообще и весь код
представляет собой одну большую функцию – prg. Понятно, что
agp1.fmsd 1.02.10
78
между отдельными операторами этой функции может существовать
некоторая зависимость (или независимость). Рассмотрим эту зависимость подробнее. В задании [75, Динамическая память] требуется
разработать три функции для текстового накопителя:
• void addStr ( const char *str); – добавления строки текста в оперативную память компьютера;
• void priMem (); – вывод текста в файл стандартного вывода;
• void freeMem (); – освобождение захваченной памяти.
По требованиям, эти три функции имеют доступ к одной глобальной
переменной – указателю на символы (char*). Понятно, что изменения в названии переменной приводит к необходимости менять код во
всех трех функциях. Операторы в этих функциях достаточно сильно
связаны друг с другом.
Еще один пример достаточно сильно связанных друг с другом
операторов можно посмотреть в задании [79, Вывод локального времени]. В ней предлагается разработать шесть функций, которые значения переменных типа time t или структурного типа struct tm выводят в строчку со временем суток, либо датой года, либо датой года
и временем суток. В принципе, даже если каждую из таких функций разрабатывать отдельно, то все равно окажется, что их операторы связаны между собой требованиями к общей функциональности.
Например, изменения требований к формату времени затрагивает
четыре из шести функций.
Примером мало связанных друг с другом (то есть, независимых
друг от друга) операторов являются, скажем, операторы функции
чтения файлов fread из библиотеки < stdio.h > и функции isdigit из
библиотеки < ctype.h >. Изменения требований к чтению файлов
не должны сказываться на таблице соответствия кодов символам и
наоборот.
Итак, код функции prg каким-то способом был разделен на модули. В [48] у модулей определяются две характеристики: прочность и
agp1.fmsd 1.02.10
79
сцепление (другими словами, определяются требования к прочности
каждого отдельного модуля и сцеплению между модулями).
Список требований к прочности упорядочен по мере ужесточения
требований. Итак, модуль называется:
• Прочный по совпадению – модуль, между операторами и переменными которого нет осмысленных связей. Трудно привести
пример такого модуля, так как он не выполняет никаких разумных функций.
• Прочный по логике – при каждом вызове выполняет выбранную функцию из набора (функций) связанных с ним. Тут подразумевается, что, скажем, одна и та же функция, может использоваться для вызова синуса, косинуса, тангенса и т.д, а
конкретная функция задается специальным параметром-переключателем.
Сейчас практически невозможно встретить такой код. Примером может считаться, Обработчик окна в смысле Windows 3.11:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMessage,
WPARAM wParam, LPARAM lParam)
Параметр uMessage представляет собой такой переключатель,
который вызывает обработку того или иного события. А сама
функция состоит из жуткого и длинного оператора swith−case
с миллионом альтернатив. Из пары параметров wParam, lParam
путем нетривиальных усилий добывались параметры для обработки соответствующего события. В настоящее время каждый
отдельный делегат-обработчик события в смысле .Net представляет собой некоторый отдельный case обработчика окна в
смысле Windows 3.11.
• Прочный по исполнению – выполняет несколько не связанных
функций, отнесенных разработчиком к одному модулю потому,
что они необходимы в один и тот же период работы системы.
Для системы копирования данных с некоторого WEB - сервера
в БД это может быть функция, которая перед началом работы
последовательно открывает соединение с БД и устанавливает
соединение с веб-сервером.
agp1.fmsd 1.02.10
80
• Процедурно прочный – последовательно выполняет набор тех
связанных с ним функций, которые непосредственно относятся
к некоторой процедуре (из реальности) решения задачи. Таким,
например, является модуль с функций ’закрыть клапан y, прочитать значение температуры парового котла и занести его в
журнал’.
• Коммуникационно прочный модуль – это процедурно прочный
модуль с одним дополнительным ограничением: все его функции связаны по данным. Например, модуль ’прочитать следующей запись и обновить главный файл’ коммуникационно прочен, так как обе функции связаны между собой тем, что обе
работают с одной и той же записью.
• Функционально прочный – это модуль, выполняющий одну определенную функцию, такую, как ’закрыть клапан y’, ’выполнить
команду РЕДАКТИРОВАТЬ’ или ’подвести итог по сделкам за
неделю’.
• Информационно прочный – выполняет несколько функций, причем все они работают с одной и той же структурой данных и
каждая представляется собственным входом. Например, набор
функций fread, fwrite, fgetpos, fsetpos.
Сцепление – еще один важнейший способ увеличить независимость модулей, уменьшение сцепления означает ослабление связи
между ними. Сцепление модулей, т.е. мера взаимозависимости модулей по данным, характеризуется как способом передачи данных,
так и свойствами самих этих данных. Проанализировав любую пару модулей, можно определить, к какому из шести видов относится
сцепление между ними, либо установить, что между ними прямого
сцепления нет.
Цель проектирования состоит в определении таких сопряжений
между модулями, чтобы все данные передавались между ними в
форме явных и простых параметров. Как и раньше, чтобы понять
agp1.fmsd 1.02.10
81
важность этой цели, рассмотрим ниже шесть видов сцепления, начиная с самого жесткого сцепления (наихудший случай).
Виды сцепления:
• сцепление по содержимому – два модуля сцеплены по содержимому, если они прямо ссылаются на содержимое другого (переменные или поля);
• сцепление по общей области (и сцепление по внешним данным)
– модули сцеплены по общей области, если они ссылаются на
одни и те же глобальные переменные;
• сцепление по управлению – модули сцеплены по управлению,
если один явно управляет функционированием второго, например, используя код конкретной функции в качестве параметра
(такое сцепление обычно соседствует с прочными по логике модулями);
• сцепление по формату – группа модулей сцеплена по формату,
если они используют одну и туже структуру данных (первый,
например, – (fwrite, fwread), второй – (fprintf, fscanf));
• сцепление по данным – два модуля сцеплены по данным, если
один вызывает другой и все входные и выходные параметры
вызываемого модуля оказываются простыми (по-видимому, в
текущих условиях не достижимый идеал). Ослабление сцепления по формату до сцепления по данным, полезна с точки
зрения принципа минимизация доступа к данным.
Степени прочности и сцепления можно использовать для оценки
существующего проекта и как руководящий принцип при проектировании новой программы. Высокая прочность и слабое сцепление
способствует независимости модулей, поскольку они сводят к минимуму их взаимодействие и их предположения друг о друге.
В качестве иллюстрации ко всему сказанному рассмотрим работу [79, ВЫВОД ЛОКАЛЬНОГО ВРЕМЕНИ]. В ней предлагается
разработать шесть функций:
agp1.fmsd 1.02.10
82
---- File:./src/dttmtoa/dttmto.h
#ifndef _INC_DTTMTO_H
#define _INC_DTTMTO_H
#include <stdio.h>
#include <string.h>
#include <time.h>
//
//
//
функции для преобразования времен в текстовое представление
char * dttoa ( time_t dtTm, char *b
char * tmtoa ( time_t dtTm, char *b
char * dttmtoa( time_t dtTm, char *b
= 0);
= 0);
= 0);
// дату в строку
// время в строку
// дату и время в строку
char * dtToA ( const struct tm * dtTm, char *b = 0);
char * tmToA ( const struct tm * dtTm, char *b = 0);
char * dtTmToA( const struct tm * dtTm, char *b = 0);
#endif
---- End Of File:./src/dttmtoa/dttmto.h
Все шесть функций выполняют одну отдельную функцию: конвертируют время из одного из двух форматов в текстовое представление.
Если их все расположить в одном файле модуль нельзя признавать
как информационно - прочный, так как функции работают не с одной и той же структурой данных, а с двумя – struct tm и time t.
Таким образом, если этот набор разделить на два файла, то можно получить два, уже информационно - прочных модуля. С другой
стороны, по условию работы все функции имеют доступ к одному
общему буферу данных для хранения тестового представления времени. Значит между этими модулями существует сцепление по сцепление по общей области. Для окончательного разделения модулей
требуется для первых трех функций (работают с time t) сделать
один буфер, для вторых трех (работают с struct tm) – второй буфер. Далее, функции можно написать так, что бы первая группа
agp1.fmsd 1.02.10
83
не обращалась к функциям второй группы и наоборот. Тогда сцепление между модулями будет отсутствовать. Но, с другой стороны,
правила преобразования даты и времени будут отдельно находится
в первой группе, отдельно – во второй. К таким правилам относится необходимость добавлять единицу к номеру месяца в году, либо
добавлять 1900 к текущему году, чтобы получить год в привычном
виде. Можно разрешить функции dttmtoa(time t dtTm) обращаться
к функции dtTmToA(const struct tm * dtTm) для выполнения преобразования. Тогда правила преобразования даты и времени будут
находится в одном модуле, а между модулями возникнет сцепление
по данным. Это в том случае, если структуру struct tm трактовать
как простой тип.
Замечание
Простыми имеет смысл называть классы, которые предоставляются текущей системой программирования. Естественно простой класс, скорее всего, не будет меняться завтра или послезавтра).
В противном случае, если простыми считать только классы вроде
целых чисел, то возникшее сцепление будет считаться сцеплением
по формату.
2.4.2
Композиционный анализ
Прочность модуля, сцепление и другие рассматривавшиеся характеристики полезны при оценке альтернатив, но они не определяют явно
ход мысли при проектировании. В рамках композиционного проектирования имеется процесс, называемый композиционным анализом, –
нисходящий процесс продумывания проекта. Композиционный анализ включает анализ структуры задачи и анализ преобразования
данных по мере их прохождения сквозь эту структуру. Эта информация используется для разбиения задачи на ’слои’ модулей. Каждый
модуль рассматривается затем как отдельная подзадача, и анализ
повторяется рекурсивно.
agp1.fmsd 1.02.10
84
Имеются три основные стратегии декомпозиции при применении
композиционного анализа.
• Декомпозиция STS (source/transform/sink) предполагает деление задачи на функции, занимающиеся получением данных,
изменением их формы и затем доставкой в некоторую точку
вне задачи;
• Операционная декомпозиция (transaction decomposition) состоит в делении задачи на функции - ’сестры’, каждая из которых
выполняет операции отдельного типа;
• Функциональная декомпозиция – это деление задачи на функции, выполняющие преобразование данных.
STS- декомпозицию обычно применяют для выделения первого
слоя модулей, а затем, к каждой подзадаче применяется одна из трех
стратегий, причем выбор зависит от характеристик задачи.
Операционная и функциональная декомпозиции – это, в основном, интуитивные процессы, и о них немногое можно добавить к
тому, что уже сказано. Напротив, STS- декомпозиция – более сложный процесс, и его можно кратко описать в виде следующих шагов:
.(
Основываясь на потоке данных в задаче, обрисуйте ее структуру в
виде 3-10 процессов;
Определите главный входной поток данных, поступающий в задачу,
и главный выходной поток;
Проследите за изменением входного потока данных при прохождении по структуре задачи. При этом вы обнаружите два явления:
входной поток будет изменять форму, становясь все более абстрактным по мере того, как вы следуете по структуре задачи, и, в конце
концов, вы попадаете в точку, где он как будто исчезает. Точка, где
он появляется в последний раз, называется точкой наивысшей абстракции входного потока.
agp1.fmsd 1.02.10
85
Выполните аналогичный анализ, выходного потока данных, начиная с ’конца’ структуры задачи и двигаясь в обратном направлении.
Определите точку, где выходной поток впервые появляется в своей
самой абстрактной форме;
Эти точки представляют особый интерес, поскольку они делят
задачу на наиболее независимые части (обычно три);
Представьте эти части как функции и определите модули, выполняющие каждую из этих функций; Эти модули становятся подчиненными по отношению к модулю, декомпозиция которого выполняется.
Определите сопряжения этих модулей. В этот момент необходимо
только определить виды данных для каждого сопряжения. То есть,
следует дать качественное описание входных и выходных аргументов, не заботясь об их точной природе (порядок, атрибуты, представление). Детали каждого сопряжения будут определены в одном из
последующих процессов проектирования – проектировании по контракту (2.3.3).
Процесс декомпозиции продолжается на следующих, более низких уровнях в иерархии, вплоть до момента остановки. Этот момент
определяется по следующему правилу: логика модулей должна стать
интуитивно понятной (это, вероятно, означает, что размер модуля не
будет превосходить 50 операторов).
Результатом анализа является иерархическая структурная схема,
отражающая структурные отношения между всеми модулями (кто
кого вызывает), функции каждого модуля и сопряжения между ними. Обозначения для таких схем описаны Г.Майерсом в [23].
2.4.3
Категории функциональных типов контракта
Сигнатуры функций из контракта абстрактного типа данных позволят разделить эти функции на несколько категорий при помощи
функциональной стрелки:
• Домен типа может вообще отсутствовать в функции. Эти функции не очень нужны в проектируемом типе выполняют вспо-
agp1.fmsd 1.02.10
86
могательную роль. После реализации такая функция окажется
статическим методом.
• Домен типа появляется только с правой стороны функциональной стрелки – такая функция называется конструктором. Эти
функции из ничего (или из чего-то внешнего по отношению к
домену типа) создают элемент домена типа.
• Домен типа появляется только с левой стороны функциональной стрелки – такая функция называется функцией выхода,
она возвращают информацию об элементах домена типа.
• Домен типа появляется с обеих сторон функциональной стрелки – такая функция называется функцией перехода. Один элемент домена типа заменяется на другой элемент. После реализации о таких методах говорят, что объект переходит в другое
состояние при помощи этих методов.
Терминология далеко не устоявшаяся, соответствие терминов смотри
в таблице 2.3.
2.4.3.1 Терминология, используемая в литературе
Термины Б.Мейера, RLG – группа языка RAISE, А.А.Степанов,
абстрактные автоматы.
agp1.fmsd 1.02.10
87
Таблица 2.3 – Терминология
обозначение
T
X,Y
почти
проект-е
абстрактные
по
автоматы
контракту
множество
состояний
любые множества,
могут содержать
T как сомнож.
RLG
Степанов
тип
интереса
типы
X→
↦ Y
X→
↦ T
функция входа
функ-создания
T×X→
↦ T × Y функция перехода функ-команда генератор
команда
T×X→
↦ Y
функция выхода
функ-запрос
наблюдатель
2.4.4
Категоричность и полнота спецификации
Обсуждения нескольких примеров спецификаций должно рано или
поздно привести к вопросу о том, как узнать, что разрабатываемая
спецификация достаточная для работы? С точки зрения разработки ПО это значит, что методов класса достаточно, чтобы решить
поставленную в спецификации к ПО задачу. В привычном для программистов примере со стеком (или очередью) очевидно, что если
удалить из спецификации стека функцию push – то поставленная
задача разработки стека не будет решена. Значит, методов (и или
других сущностей) не достаточно. В примере с кольцом целых это
далеко не очевидно. Доказательство достаточности этих требований
для работы (в этом случае для работы всех, кто пользуется арифметикой) заняло не один десяток лет и потребовало усилия не одного
хорошего математика. В терминах, принятых в области разработки
ПО, используется термин ’полнота спецификации’.
Замечание
Понятно, что все рассуждения о спецификации выполняются в
предположении, что её удалось написать непротиворечивой.
agp1.fmsd 1.02.10
88
Достаточная полнота
Спецификация типа T является достаточно полной тогда и
только тогда, когда её аксиомы позволяют для каждого выражения expr решить следующие задачи:
• определить, является ли expr корректным;
• если expr – выражение запрос и его корректность доказана, то представить значение expr в виде, не включающем
никаких значений типа T (см. [60, стр.229]).
Замечание
Более подробно обсуждение проблемы полноты спецификации
можно посмотреть в соответствующем разделе Б.Мейера см.
[60, стр.227].
2.4.4.1 Полнота спецификации и метод разработки RAISE
В группе, которая занимается языком формальных спецификаций RSL и методом разработки ПО под названием RAISE (RAISE
Development Method), в явной форме описывается процедура создания достаточно полной спецификации (см. [2, стр.10]). Эта процедура
содержит следующие важные шаги:
For each possible combination of non-derived observer
and non-derived generator, define an axiom expressing the
relation between them. We have three non-derived generators
and two non-derived observers, These axioms are called observergenerator axioms.
agp1.fmsd 1.02.10
89
Для каждой возможной комбинации не выводимых функций - наблюдателей (см. 2.4.3.1) и не выводимых функций генераторов требуется определить аксиому, которая выражает отношения между ними.
Такие аксиомы называются аксиомы наблюдателей - генераторов.
Add axioms expressing the notion that the non-derived
generators maintain consistency.
Далее, добавить аксиомы, которые выражают как не выводимые генераторы поддерживают условия целостности абстрактного типа.
Где observer – это функция типа, которая из переменой типа извлекает нечто меньшее, в случае стека – это функция top (выражение
- запрос у Б.Мейера [60, стр.230]). Generator – это функция типа, которая создает или меняет переменную абстрактного типа, в случае
стека – это функция push. Если посмотреть на формальное описание кольца целых чисел (или поля вещественных чисел), то можно
заметить, что именно так поступали математики при разработке соответствующих объектов (кольца и поля). Понятно, что кольцо целых чисел можно трактовать как абстрактный тип данных для целочисленной арифметики в любом языке программирования, а поле
вещественных чисел – как абстрактный тип данных для арифметики
с плавающей точкой. Имея такие примеры, как стек, очередь, целочисленную арифметику, арифметику с плавающей точкой и мнение
авторов метода разработки RAISE можно быть уверенным, что такая
процедура позволяет создавать достаточно полные спецификации.
Этот способ для описания поведения функций из проектируемого
абстрактного типа данных, добиваясь полноты спецификации, восходит к 19 веку. В частности, похожим способом в 1861 году Грассман
описывал арифметику натуральных чисел ([81]).
2.4.4.2 Понятие категоричности
В процессе -> надо или не надо? Спецификация удовлетворяет
определению теории Степанова,
agp1.fmsd 1.02.10
90
теория
Теорией называется множество истинных утверждений (см. [88,
Теории и модели])
Абстрактный тип в смысле Б.Мейера (то есть, спецификация), как
множество требований, является множеством истинных утверждений, и, значит, является теорией.
модель
Множество элементов, для которого определены все операции
(в терминах спецификации – функции) теории и истинны все
предложения теории, называется моделью теории.
На множестве объектов класса (как реализованного абстрактного типа) очевидно, определены все операции теории (функции абстрактного типа) и истинны все условия целостности. Таким образом, класс
можно считать моделью.
Если между двумя классами (реализациями абстрактного типа)
существует отображение (m), сохраняющее функции, то классы будут называться изоморфными. То есть, для каждой функции класса
f выполняется:
f(m(x), m(y) = m(f(x, y))
Спецификация будет называться категоричной, если все её реализации изоморфны.
Группа рациональных чисел по сложению является категоричной
спецификацией, наследование можно применить добавив к ней требования к функции умножения. После такого наследования группа
рациональных чисел превращается в поле рациональных чисел. Из
четырех ’минимальных’ возможностей наследования (добавление абстрактного метода, добавление поля, добавление метода, переопределение метода [78, стр.50]) был добавлен новый метод (функция
умножения). Переопределение функции сложения невозможно в силу категоричности поля рациональных чисел.
agp1.fmsd 1.02.10
2.5
91
Применение языка формальных спецификаций RSL
C введением в язык RSL (полное название RAISE specification language)
можно ознакомиться в следующих документах: [32, 12, 2, 56]. Введение в метод разработки ПО RAISE см. [2, 13]. Некоторое количество
RSL - схем в ASCII - стиле можно увидеть в статье [68].
В работе [74] применялось абстрактное описание типов для анализа примера Р.Мартина (см. [22]) по вопросу нарушения принципа подстановки Б.Лисков. Было показано, что при помощи наследования нарушались аксиомы базового класса. Это означает, что тип
производного класса отличался от типа базового (точнее, тип производного класса не являлся подтипом базового).
При помощи языка RSL можно записывать спецификации как в
аппликативном, так и в императивном стиле. Аппликативный стиль
записи похож на применение функций. При его использовании не
используются переменные и для программиста он может выглядеть
достаточно непривычно. Использование переменных является характерной особенностью императивного стиля записи формальных спецификаций, что приближает спецификацию к языку программирования.
2.5.1
Утилита RSLTC
Для работы со спецификациями на языке RSL разработано несколько программных продуктов. Основной продукт – это утилита RSLTC
(type checker), которая может проверять корректность спецификации
(имеется ввиду статическая типизация и проверка синтаксиса схемы), подготавливать спецификацию к виду пригодному для печати
в текстовом стиле (pretty printing, см. [6], выполняет форматирование текста) и генерировать код для некоторых языков программирования (в частности, для C++). В принципе, для разработки спецификаций можно остановиться только на этой утилите, добавляя в
программную документацию спецификацию в виде ASCII - текста.
Но в описании пакету listings [16] в списке на странице 14 обнаружен
agp1.fmsd 1.02.10
92
язык RSL. Использование пакета дало положительные результаты,
текст на языке RSL отображается с математическими символами.
Это делает текст документа более читабельным.
Настройка пакета listings: в преамбуле документа нужно добавить строки:
\usepackage {listings}
\lstloadlanguages {RSL, SQL, [Sharp]C} % выбор языков программирования
\lstset{
extendedchars=true , % добавить не латиницу
}
Подключение файла с кодом языка программирования:
\lstinputlisting[language=RSL,frame=tlBR,
caption={код RSL}] {./src/rsl/a_peano1.rsl}
Рамка tlBR (top, left, bottom, right) задает количество линий на соответствующей стороне. Маленькая буква – одна линия, большая буква
– две. Можно строчки кода непосредственно вставлять в текст документа и нумеровать их (см. [16, стр.15]). Для ссылок на код можно
использовать метки. Например, так:
\lstinputlisting[language=RSL,frame=tlBR,
caption={Код RSL}, label=code:apeano1] {./src/rsl/a_peano1.rsl}
Замечание
При использовании с версией LaTex, которым строился документ, обнаружился некоторый недостаток:
Рисунок 2.31 – Некорректное отображение слова ’is’
agp1.fmsd 1.02.10
93
Поэтому в примере с проектом Гавань, оригинальная спецификация изменена. Функция Is docked написана с большой буквы.
Далее, в каталог к файлам LaTex-а -а нужно положить файлы
стилей boxedminipage.sty и rslenv.sty. Затем, в преамбулу документа
добавить строчку использования пакета для RSL:
\usepackage{rslenv}
2.5.1.1 Варианты командной строки утилиты RSLTC
См. [6, Tool components available]:
rsltc <file>
: Type check
rsltc -pp <file> : Parsing (no type check) plus pretty printing of current module
rsltc -c <file> : Type check plus confidence condition generation on current module
rsltc -cc <file> : Type check plus confidence condition generation on all modules
rsltc -d <file> : Parsing (no type check) plus display of module dependencies
rsltc -g <file> : Generation of VCG file to show module dependencies
rsltc -m <file> : Translation to SML
rsltc -c++ <file>: Translation to C++
rsltc -cpp <file>: Translation to Microsoft’s Visual C++
rsltc -pvs <file>: Translation to PVS
2.5.2
Спецификации языка RSL
Спецификация представляет собой набор модулей. Модули делятся
на несколько групп: схемы, объекты и теории (см.2.6.2). Схемы (могут быть параметризованные схемы – шаблоны, см. [12, 2.11] 2.5.8)
является выражениями для классов (class expression), объекты – экземплярами класса (см. [12, 2.12]), теории см. 2.6.2.
Базовые выражения для классов содержат объявления нескольких видов (декларации), которые начинаются ключевым словом class
и заканчиваются ключевым словом end. Остальные выражения для
классов см. [12, 2.10]. Таким образом базовые схемы имеют вид:
scheme id =
class
declaration_1
. . .
declaration_n
end
agp1.fmsd 1.02.10
94
Идентификатор схемы id должен совпадать с именем файла, в котором она содержится. Имя файла должно начинаться с буквы. Каждая декларация начинается с одного из ключевых слов (object, type,
value, variable, channel, axiom, test_case) за которыми следуют определения. Декларации не являются обязательными и могут повторяться. Соответствие текстовых версий символов и символов для
LaTex см. 2.5.2.6 или [12, стр.65].
2.5.2.1 Декларации переменных
В следующей схеме, в декларации variable для определения значений переменных используются типы, встроенные в язык RSL:
---- File:./src/rsl/vars.rsl
scheme vars = class /* схема набрана безобразным образом, что бы показать
не важность пробелов, табуляций и символов новой строки */
variable p1: Bool := false, p2: Int
:= -1, p4:Real := 2.718281828, p5:Char:=’x’, p6:Text:=
"hello, world!", p3:Nat
-- натуральные числа содержат 0
value
idx:Int :- idx > 0 /\ idx < 10
end
---- End Of File:./src/rsl/vars.rsl
Идентификатор схемы vars, имя файла vars.rsl. Кроме декларации
переменных в схеме присутствуют два вида комментариев. Существует еще один встроенный тип Unit (с единственным значением
круглые скобки ()). Его можно рассматривать как аналог типа void
для функций в языке Си. В декларации value можно задавать величину с ограничениями, величина idx (это не переменная) может
принимать значения от 1 до 9. Список операций над выражениями
соответствующих типов:
• Bool – \/ , /\, => , ~;
• Int – +, -, *, /, \, **, <, > , >=, <=, abs, real;
agp1.fmsd 1.02.10
95
• Real – +, -, *, /, **, <, > , >=, <=, abs, int;
• Char – сравнения: =, ~=;
• Text – операции над списком символов;
• Unit – операции отсутствуют.
Операции сравнения применимы ко всем типам кроме типа Unit.
Операция остаток от деления на целое: ’\’ не применима к вещественным числам. Символ ’**’ является символом операции возведения в
степень.
2.5.2.2 Декларации величин и функций
Декларация начинается ключевым словом value. В этой декларации описываются функции и константы. Функции можно задавать
явно, не явно, аксиоматически и про помощи выражения лямбда:
---- File:./src/rsl/funcs.rsl
scheme funcs = class
value
suc: Int -> Int
-- явно заданная функция
suc(x) is x + 1
, sqrt : Real -~-> Real -- частичная
sqrt (x) as root
-- не явно заданная функция
post
-- пост условие
root * root = x /\ x >= 0.0
pre
x>= 0.0
-- предусловие
, tan : Real -~-> Real -- не явно задан тангенс
, sin : Real -> Real
-, cos : Real -> Real
-value
-- лямбда выражение
sum : Real >< Real -> Real = -\ (l: Real, r: Real) :- l + r
, eqv : Real -> Real
-- аксиоматическое сокращенное: eqv
eqv (x) is
x
-и полное
: pow
, pow : Real >< Int -> Real
axiom
all b : Real, e : Int :pow (b, e) is b ** real e
end
---- End Of File:./src/rsl/funcs.rsl
agp1.fmsd 1.02.10
96
Что бы применить функцию, справа от имени функции используются круглые скобки с некоторым значением: sin(0.0). Существует
специальная величина chaos – обозначает неопределенное поведение
программного обеспечения ([56, стр.6], [32, стр.22], [5, стр.12]). Величины (константы) можно задавать явно, или неявно или неявно с
некоторыми ограничениями.
---- File:./src/rsl/vals.rsl
scheme vals = class
value
idx :Int
:- idx > 0 /\ idx < 10 -- неявно, есть ограничения
, zero:Int =0
-- явно
, Pi :Real
-- неявно
end
---- End Of File:./src/rsl/vals.rsl
2.5.2.3 Расширение схем
При разработке одной схемы можно использовать другие, ранее
разработанные схемы. Новая схема может пользоваться всеми величинами, функциями, типами и т.д., которые объявлялись в предыдущих. Такое расширение несколько напоминает наследование. Расширение схем выполняется при помощи ключевых слов extend и with
следующим образом:
---- File:./src/rsl/funcs2.rsl
funcs,
vals
scheme funcs2 = extend funcs with extend vals
with class
axiom
all x : Real :- sin(x) * sin(x) + pow(cos(x),2) = 1.0
,sin(Pi) = 0.0
end
---- End Of File:./src/rsl/funcs2.rsl
В новой схеме задаются аксиомы для задекларированных в схеме
funcs.rsl двух функций (то есть, завершили аксиоматическую декларацию функций sin, cos) и задекларированой в схеме vals.rsl величины (Pi). И заодно продемонстрировали применение функции pow –
возведение в степень. Названия расширяемых схем должны присутствовать в начале новой схемы.
agp1.fmsd 1.02.10
97
2.5.2.4 Конструирование типов
В этом разделе рассматриваются средства языка RSL для конкретизации обозначений на схемах потоков данных. Примеры:
---- File:./src/rsl/types.rsl
scheme types = class
type
Latitude =
-- подмножество Real
{| b : Real :- b >= -90.0 /\ b <= 90.0 |}
, coor
= Latitude >< Real -- прямое произведение
, Colour
==
-- перечисление
red | green | yellow -- простой вариант
, nNums
= Nat -inflist
-- бесконечный список
, answers = Bool -list
-- конечный список
, map
=
-- отображение из градусов
coor -m-> Nat >< Nat -- в пиксели экрана
, iNums
= Int -set
-- конечное множество
, rNums
= Real-infset
-- бесконечное множество
, Ship
-- неопределяемый тип, теперь
-- это имя можно использовать
value
tonnage : Ship -> Nat
-- тоннаж судна
end
---- End Of File:./src/rsl/types.rsl
Новые тип может создаваться как не определяемый тип или сорт
(в документации к RSL используется термин абстрактный тип, но это
определение противоречит абстрактному типа Б.Мейера) – для такого типа задается только его имя. Для абстрактных аппликативных
спецификаций естественно использовать обозначения, которые были
использованы на схемах потоков данных. Далее, тип может создаваться как подмножество существующего типа, как прямое произведение множеств, как вариант (variant, простая версия типа вариант
похожа на перечисление языка Си, см. [56, стр.41] или [12, стр.98]),
как бесконечный или конечный список, как отображение, как конечное или бесконечное множество как запись (short record, см. [12,
стр.125] ), или как объединение (union). При определении объединения используется символ =, а не символ == (см.[12, стр.123]). Для
доступа к отдельному элементу списка или отображения (похоже
на операцию применения функции) используются символы круглых
скобок: ( ). В случае списков операция называется индексирование
agp1.fmsd 1.02.10
98
(первый индекс равен 1), в случае отображений – применение отображения. В качестве дополнительного примера рекурсивно зададим
неустойчивую последовательность Мюллера (см.[44, стр.6]), которая
демонстрирует накопление ошибки при вычислениях с плавающей
точкой:
---- File:./src/rsl/muller/mlrsec.rsl
-- Кулямин. Стандартизация и тестирование реализаций мат.функций,
-- работающих с числами с плавающей точкой. стр.6
scheme mlrSec = class
value
x: Real-inflist
axiom
x(1) = 2.0
,x(2) = -4.0
,all n : Nat :x(n+2) = 111.0 - 1130.0/x(n+1) + 3000.0 / x(n+1) * x(n)
end
---- End Of File:./src/rsl/muller/mlrsec.rsl
Отображения могут быть детерминированные и недетерминированные. В детерминированных отображениях, как и в функциях,
каждому элементу из домена отображения (см. таблицу 2.7, аналог
области определения функции) соответствует один элемент из множества значений. В недерминированных – это не так.
2.5.2.5 Тестовые варианты
Язык RSL предоставляет возможность записывать тестовые варианты для будущего тестирования ПО на раннем этапе работы, в
момент разработки абстрактного типа данных. Для этого используются декларации, которые начинаются с ключевого слова test_case
(тестовый вариант):
---- File:./src/rsl/tests.rsl
agp1.fmsd 1.02.10
99
-- Нечаев. Числовые системы, 1975
scheme tests = class
type
Numbers
value
zero : Numbers
, a: Numbers
, b: Numbers
, c: Numbers
, sum: Numbers >< Numbers -> Numbers
test_case
-- стр.46 Аксиомы группы
[G2_check]
sum(a, sum(b, c)) = sum ( sum( a, b), c) ,
[G3_check]
sum( zero, a ) = a
end
---- End Of File:./src/rsl/tests.rsl
Примеры практического использования при разработке функций вещественных переменных см. [41, 40].
2.5.2.6 Таблицы обозначений
В подразделе представлены таблицы со списками операций над
выражениями соответствующих типов и других обозначений:
Таблица 2.4 – Символы логики
символ LaTex-a
false
true
∼
∧
∨
⇒
∀
∃
∃!
≡
ASCII версия
false
true
~
/\
\/
=>
all
exists
exists!
is
что значит
[80] [56]
7
7
отрицание
7
логическое И
7
логическое ИЛИ
7
влечет
7
кв.всеобщности
7
кв.существования
7
кв.существования
7
эквивалентность
7
[12]
21
21
23
23
23
23
25
25
25
24
agp1.fmsd 1.02.10
100
Таблица 2.5 – Символы для множеств
символ LaTex-a
{}
{a}
|
..
∩
∪
\
×
∈
̸
∈
⊂
⊆
⊃
⊇
card
ASCII версия
{}
{a}
|
..
inter
union
\
><
isin
~isin
<<
<<=
>>
>>=
card
что значит
[80]
пустое множество
скобки для множества
сокр.опр.множества
диапазон
пересечение
объединение
разность
прямое произведение 2.5.2.4
принадлежит
не принадлежит
строго включается
включается
строго включается
включается
количество элементов
[56]
20
20
21
20
21
21
21
11
21
21
21
21
21
21
21
[5]
54
54
56
55
57
57
57
32
56
56
57
57
57
57
58
Таблица 2.6 – Символы для списков
символ LaTex-a
⟨⟩
..
| in
()
̂︀
hd
tl
len
elems
inds
ASCII версия
<. .>
..
| in
()
^
hd
tl
len
elems
inds
что значит
[80]
скобки списка
2.5.4.4
диапазон целых
сокр.опред.списка
индексир. списка
конкатенация
голова
хвост
длина
множество элем-тов
множество индексов
[56]
24
24
25
65
26
26
26
26
26
26
[12]
63
64
65
66
66
67
67
67
68
68
agp1.fmsd 1.02.10
101
Таблица 2.7 – Символы для отображений
символ LaTex-a
[ ]
↦
→
|
()
dom
rng
†
\
/
∘
ASCII версия
[ ]
+>
|
()
dom
rng
!!
\
/
#
что значит
[80] [56]
скобки отображения
30
пара
30
сокр.опр.отображения
31
применение отображения
домен
32
множество значений
32
обновление отображения
32
разность с доменом
33
пересечение с доменом
33
композиция
33
[12]
74
74
76
76
77
77
77
77
77
78
Таблица 2.8 – Остальные символы языка
символ LaTex-a
→
∼
→
𝜆
skip
chaos
{|
|}
::
↔
⊢
⪯
⊑
ASCII версия
->
-~->
-\
skip
chaos
{|
|}
:::
<->
|{=
[=
2.5.3
Спецификация целых чисел Пеано
∙
что значит
всюду опред.функция
частич.опред.функция
лямбда выражение
пустая конструкция
исключительное сост.
описание
подтипа
связывание
создание записи
реконструктор записи
утв. о реализации
реализ.класса
реализ.объекта
[80]
[56] [12]
13 39
14 41
2.5.2.2
43
47 150
7
24
5
83
2.5.2.4 5
83
2.5.2.4 5
83
125
43 125
2.6.2
54
2.6.2
54
69
Все перечисленные возможности языка уже позволяют записывать
достаточно сложные абстрактные спецификации. Для примера в раз-
agp1.fmsd 1.02.10
102
деле приводится два вида абстрактной спецификации целых чисел
из [32]. Текст спецификации в ASCII - кодах:
---- File:./src/peano/peano.rsl
--операция сравнения ’=’ и ключевое слово ’is’
-имеют различный смысл, но в этом примере смысл практически совпадает.
-если в схеме появляются "глобальные переменные" - множество
-всех глобальных переменных наз. состояние - то операция = и
-is будут иметь различный смысл. is означает равно для всех состояний
-scheme PEANO =
class
type
-- завели тип N
N
value
zero: N
-- завели величину zero
-- (это не переменная, нельзя присваивать)
,succ: N -> N
-- величина - функция из N в N
axiom
-- квантор всеобщности
all n : N :-- n - это обозначение
~(succ(n) is zero) -- для каждого n результат succ(n)
,
-- не есть zero
[linear_order]
all n_1, n_2 : N :(succ(n_1) is succ(n_2)) => (n_1 is n_2)
,
[induction]
all p : N -> Bool :-- для любого предиката
-(p(zero) /\ (all n : N :- p(n) => p(succ(n))))
=>
(all n : N :- p(n))
end
---- End Of File:./src/peano/peano.rsl
Текст спецификации в стиле для LaTex:
Листинг 1: код RSL
−−
agp1.fmsd 1.02.10
103
−−
операция сравнения ′ = ′ и ключевое слово ′ i s ′
−−
имеют различный смысл , но в этом примере смысл практиче
−−
если в схеме появляются " глобальные переменные" − множ
−−
всех глобальных переменных наз . состояние − то операция
и
−−
≡ будут иметь различный смысл . ≡ означает равно для все
−−
scheme PEANO =
class
type
−− завели тип N
N
value
zero : N
−− завели величину z e r o
−− ( это не переменная , нельзя при
, succ : N → N
−− величина − функция из N в N
axiom
−− квантор всеобщности
∀ n : N ∙
−− n − это обозначение
∼( s u c c ( n ) ≡ z e r o )
end
−− для каждого n результат s u c c ( n )
−− не есть z e r o
,
[ linear_order ]
∀ n_1 , n_2 : N ∙
( s u c c (n_1) ≡ s u c c (n_2 ) ) ⇒ (n_1 ≡ n_2)
,
[ induction ]
∀ p : N → Bool ∙
−− для любого предиката
−−
(p( zero ) ∧ ( a l l n : N ∙ p(n) ⇒ p( succ (n ) ) ) )
⇒
( a l l n : N ∙ p(n))
В стиле для LaTex Ключевые слова языка выделятся жирным,
кванторы и многое другое отображаются привычными математиче-
agp1.fmsd 1.02.10
104
скими символами.
Спецификация на RSL (так же как у Б.Мейера, см. [60, стр.193,
Формализация спецификаций]) состоит из четырех явно выделенных
разделов: типы (лучше их называть множествами), величины, к которым относятся функции, аксиомы и предусловия. Далее, в примере
присутствуют:
• N – неопределенное множество - сорт (которое после реализации превратится в полугруппу целых неотрицательных чисел
по сложению);
• В этом множестве требуется существование числа zero, это число нельзя получить в качестве результата применения функции
succ – следующее. Это требуется в аксиоме first is zero;
• Символ тильда – это отрицание в RSL;
• Собственно, функция succ отображает множество N в N;
• Аксиома линейного порядка linear order уже должна читаться
очевидным образом: для любых двух величин n1 и n2 из N
выполняется, что если результаты применения к ним функции
succ равны, то равны и сами величины n1 и n2 ;
• Следующая аксиома induction является привычной со школы
аксиомой индукции Джузеппе Пеано. С её помощью определяются сходимость и непрерывные функции. То есть, на ней
держится весь привычный матанализ, интегралы и дифференциальные уравнения.
2.5.4
Выражения языка RSL
2.5.4.1 Выражение skip
Это пустое выражение. Оно может быть использовано в ненужной
ветке выражения if. См. [56, стр.47], [32, стр.150], [5, стр.3].
agp1.fmsd 1.02.10
105
2.5.4.2 Выражение let
При помощи выражения let можно вводить дополнительные обозначения, которые будут использоваться между ключевыми словами
in и end (точнее, справа от обозначения и до end, см. [82, Спецификация прямой геодезической задачи]) этого выражения. Например:
---- File:./src/rsl/crvlen1.rsl
baseFuncs
scheme crvLen1 = extend baseFuncs with
class
value
-- длина кривой параллели на широте ltt
len: Real >< Real -> Real
len (ltt, drgs) is
let B = degree2radian(ltt)
in
degree2radian((cos(B) * N(B)) * dgrs
end
end
---- End Of File:./src/rsl/crvlen1.rsl
Схема читается привычным образом: пусть B это результат преобразования градусов в радианы величины ltt, тогда результат применения функции len это degree2radian((cos(B) * N(B)) * dgrs. Общий
вид:
let обозначение0, [обозначение1 ...]
выражении
end
in
См. [56, стр.12], [32, стр.36], [5, стр.17].
2.5.4.3 Условное выражение if- else
Условное выражение вполне привычно, выражения в обеих ветках
должны иметь одинаковый тип. Ветку else можно опускать, если
Unit это тип выражения ветки then. Есть версия для нескольких
альтернатив. Общий вид:
if выражение1
then
выражение2
[
elseif выражение3
then
выражение4
else
выражение5
end
]
См. [56, стр.8], [32, стр.21], [5, стр.12].
agp1.fmsd 1.02.10
106
2.5.4.4 Выражение case
Общий вид:
case выражение of
образец1 ->
выражение1
[
, образец2 ->
выражение2
. . .
, образецN ->
выражениеN
end
]
Выражение ’выражение’ может быть любого типа, оно сопоставляется с каждым образцом (шаблоном) последовательно, пока не закончится совпадением. В этом случае выполняется соответствующее
выражение. В следующем примере:
---- File:./src/rsl/reverse.rsl
scheme reverse = class
value
reverse : Nat -list -> Nat -list
reverse(l) is
case l of
<..>
-> <..>
, <.i.> ^ ll -> reverse(ll) ^ <.i.>
end
end
---- End Of File:./src/rsl/reverse.rsl
весь список l представляется как конкатенация двух списков: список
из одного первого элемента – <.i.> и список оставшейся части – ll. В
качестве последнего образца (шаблона) можно использовать шаблон
универсальной подстановки: символ подчеркивание _. Сопоставление с ним всегда приводит к успешному результату.
См. [56, стр.27], [32, стр.108], [5, стр.17].
agp1.fmsd 1.02.10
2.5.5
107
Общий порядок разработки ПО
После создания некоторой абстрактной аппликативной спецификации неизбежно появляется необходимость её реализации (implementation)
в том или ином виде, на том или ином языке программирования.
Одним из первых шагов такой реализации является замена не определяемого типа (сорта) на другой, конкретный тип. Это может быть
сконструированный из типов, уже встроенных в язык, или из типов,
уже разработанных в другой спецификации или других не определяемых типов. В результате следующая версия спецификации будет
считаться конкретной аппликативной спецификацией. Кроме того,
конкретная аппликативная спецификация будет считаться реализацией исходной абстрактной аппликативной спецификации.
Выражения, которые были рассмотрены до сих пор (например
кванторы существования), широко используются в таких аппликативных спецификациях. Эти тексты более привычны для чтения математикам и не совсем привычны программистам- кодерам. Поэтому, следующим шагом, можно переписывать функции, написанные
в аппликативном стиле, в императивный стиль. То есть, с использованием переменных, присвоений, циклов и других императивных
конструкций. Такая версия спецификации будет считаться конкретной императивной и являться реализацией абстрактной аппликативной спецификации. Язык RSL предоставляет средства для проверки
корректности реализации, а утилита RSLTC эту проверку может выполнять (см.раздел 2.6.2).
В качестве примера рассмотрим реализацию абстрактной аппликативной спецификации арифметики Пеано (см. [81, стр.8]) в виде
конкретной аппликативной спецификации. Абстрактная спецификация:
---- File:./src/rsl/peano/a_peano0.rsl
scheme a_peano0 = class
type
Num
value
agp1.fmsd 1.02.10
108
one: Num
, suc : Num -> Num
, sum : Num >< Num -> Num
axiom
[a_suc]
all a : Num :sum( a, one)
= suc( a)
, [a_sum]
all a, b : Num :sum( a, suc(b) ) = suc( sum(a, b))
end
---- End Of File:./src/rsl/peano/a_peano0.rsl
В ней существует не определяемое множество Num и две функции –
итератор suc и сумматор sum. Применение функций связано между
собой выражениями, которые записаны в аксиомах a suc и a sum.
Замечание
Собственно, сама абстрактная аппликативная схема подходит
для документирования тестовых вариантов для дымового тестирования будущего ПО по методу чёрного ящика. Это позволяет проектировать тесты на ранних этапах разработки ПО.
Далее, определяя неопределенный тип Num как список цифр, а
абстрактное значение one как список из цифры 1, можно получить
конкретную аппликативную спецификацию (см. [38, стр.13] или [67]):
---- File:./src/rsl/peano/a_peano1.rsl
scheme a_peano1 = class
type
Num
= dgts-list
-- неопределяемый тип Num теперь трактуется как список цифр
, dgts = {|d : Nat :- d < 10 |}
, oFlw = {|d : Nat :- d <= 1 |}
value
suc : Num -> Num
suc( s ) as ns
post
let inc =
-получить признак переполнения
-\ (n, o) :dgts >< dgts :- if o = 9 /\ n = 0 then 1 else 0 end
agp1.fmsd 1.02.10
in
hd ns = (hd s +1) \ 10
(all i : {|i :Nat :- i isin {1..len s-1} |} :ns(i+1) = (s (i+1) + inc(ns(i), s(i))) \ 10 )
/\ ns(len s +1) = if inc(ns(len s), s(len s)) >0 then
109
/\
1 else chaos
end
end
end
---- End Of File:./src/rsl/peano/a_peano1.rsl
После конкретизации типа Num появляется возможность явно описывать каким образом итератор вычисляет следующее число. Функция явно определяет каждую следующую цифру (начиная со второй)
нового списка как остаток от деления на 10 суммы соответствующей
цифры исходного списка и признака переполнения от вычисления
предыдущей цифры. А в случае первой цифры вместо признака переполнения используется единица.
Кроме того, как было замечено в [38, стр.13], роль операторов
цикла языков программирования в конкретной аппликативной спецификации играют квантор всеобщности и существования. Далее,
можно заметить, что эта же спецификация итератора suc в языке Z
выглядит менее громоздкой. Во-первых, Z позволяет вместо типа использовать практически любое множество. Поэтому в спецификации
Z нет необходимости заводить специальное множество для признака
переполнения oFlow. Так же менее громоздким выглядит определение множества цифр. Во-вторых, лямбда - выражение в Z более
компактно так как не требует сигнатуры функции.
Следующий шаг разработки будет представлен в разделе 2.5.6.7.
2.5.6
Императивные конструкции языка RSL
Как отмечалось выше, языком RSL поддерживается императивный
стиль спецификации. Это приближает его к таким языкам программирования как Си. Для этого требуются дополнительные выражения, которые будут обсуждаться в этом разделе.
Императивные выражения языка RSL разделяются символом точкас-запятой ’;’. Существует выражение skip, которое не имеет побочных эффектов и имеет тип Unit. Например:
agp1.fmsd 1.02.10
while true do skip;skip end
110
-- do nothing forever
В этом бесконечном цикле можно использовать одно выражение skip.
Второе было использовано, что бы поставить разделитель операторов.
2.5.6.1 Функции с доступом к переменным модуля
В сигнатуре функций, которые имеют доступ к переменным модуля, должны присутствовать ключевые слова write или read, затем
– тип результата применения функции.
---- File:./src/rsl/getset.rsl
scheme getset = class
variable
val : Int:=0
value
set: Int -> write val Unit
set (x) is val:=x
, get : Unit -> read val Int
get () is val
end
---- End Of File:./src/rsl/getset.rsl
См. [56, стр.46], [32, стр.140], [5, стр.17]. Выражение присваивания
имеет тип Unit.
2.5.6.2 Локальные переменные и присваивание
Примеры переменных, областью видимости которых является весь
модуль приводились в схеме раздела 2.5.2.1. Локальные переменные
(и, вообще, декларации) появляются после ключевого слова local и
существуют до соответствующего ключевого слова end. См. пример
не детерминированной функции choose ([32, стр.157]):
---- File:./src/rsl/choose.rsl
agp1.fmsd 1.02.10
111
scheme choose = class
value
choose : Nat -set -~-> Nat
axiom all s : Nat-set :choose (s) is
local value n: Nat
axiom n isin s
in n end
pre s ~= {}
end
---- End Of File:./src/rsl/choose.rsl
2.5.6.3 Конструкция ветвления if
В императивной форме конструкции if обе ветки имеют тип Unit.
Кроме того, возможна сокращенная версия конструкции if без ветки
else.
2.5.6.4 Цикл while
Выражение цикла с предусловием – цикл while. Общий вид:
while выражение do
выражение1 end
Выражение ’выражение1’ должно иметь тип Unit.
2.5.6.5 Цикл until
Выражение цикла с после условием – цикл until.
do выражение1 until
выражение end
Выражение ’выражение1’ должно иметь тип Unit.
2.5.6.6
Цикл for
for огр_список do
выражение1 end
agp1.fmsd 1.02.10
112
В следующем примере используется локальная переменная f. В ней
при помощи цикла for старое состояние переменной умножается на
переменную цикла counter, после чего результат запоминается. Оператор цикла и императивная конструкция возврата значения разделяются символом точка-с-запятой ’;’: Само выражение цикла for, как
и предыдущие, имет тип Unit.
---- File:./src/rsl/factorial.rsl
scheme factorial = class
value
fct : Nat -> Nat
fct (i) is
local variable f: Nat:= 1 in
for counter in <. 1..i .> do
f:=f*i
end; f
end
end
---- End Of File:./src/rsl/factorial.rsl
2.5.6.7 Использование императивных конструкций
После освоения цикла for можно реализовать конкретный аппликативный модуль a peano1 раздела 2.5.5 в виде конкретного императивного модуля:
---- File:./src/rsl/peano/c_peano1.rsl
scheme c_peano1 = class
type
Num
= dgts-list
, dgts = {|d : Nat :- d < 10 |}
, oFlw = {|d : Nat :- d <= 1 |}
value
one: Num = <.1.>
, inc: dgts >< dgts -> oFlw =
-\ (n, o) :dgts >< dgts :- if o = 9 /\ n = 0 then 1 else 0 end
, suc : Num -> Num
suc( s ) is
local variable
agp1.fmsd 1.02.10
ns: Num
113
:= <.(s(1)+1 ) \ 10.>
in
for i in <. 1 ..(len s) -1.> do
ns := ns ^ <. (s(i+1) + inc(ns(i) , s(i))) \ 10.>
end;
if (inc(ns(len s), s(len s)) > 0) then ns:= ns ^
<.1.> end;
ns
end
end
---- End Of File:./src/rsl/peano/c_peano1.rsl
Замена квантора всеобщности на конструкцию цикла выглядит вполне
прозрачной:
local variable
-- 1
hd ns = (hd s +1) \ 10
ns: Num := <.(s(1)+1 ) \ 10.>
in
-- 2
i isin {1..len s-1 ... см.4
for i in <. 1 ..(len s) -1.> do
-- 3
ns(i+1) = (s (i+1) + inc(ns(i), s(i))) \ 10
ns := ns ^ <. (s(i+1) + inc(ns(i) , s(i))) \ 10.>
end;
-- 4
см.2 ... + inc(ns(len s), s(len s)
if (inc(ns(len s), s(len s)) > 0) then ns:= ns ^
<.1.> end;
ns
end
К схеме в качестве комментария добавлены строчки из аппликативной конкретной спецификации:
1. инициализация цикла – очевидная;
2. условие повторения цикла отличается возможно на одну итерацию, в цикле не выполняется итерация при переполнении в
самом старшем разряде;
3. вместо сравнения (с учетом переполнения) очередных элементов нового списка ns(i) и исходного s(i), выполняется конкатенация уже построенной части нового списка с очередным вычисленным элемента (таким образом, равенство из абстрактной
спецификации выполняется);
agp1.fmsd 1.02.10
114
4. единица, которая получается при переполнении в старшем разряде исходного списка добавляется к новому списку.
Таким образом, полученная императивная реализация вплотную
приближает спецификацию к обычным языкам программирования
(С++ или С#). Более того, при помощи последовательного перехода
от абстрактной аппликативной спецификации к конкретной аппликативной и, далее, к конкретной императивной, удается выполнить
пожелание из статьи Д.Л.Парнаса (см. [50, 9]) двигаться шаг за шагом от пользователя (тут от желания пользователя получить приложение) к приложению. Точнее, ’систематически выполнять небольшие шаги, чтобы обеспечить соответствие между абстрактным представлением пользователей о системе и конкретным работающим кодом’.
2.5.7
Операции над классами
• extend – расширение класса с помощью другого класса (аналог наследования) (см. [12, стр.27], [39, Площадь сферического
треугольника]):
extend класс1 with класс2
• use for in – замена имен класса (см. [12, стр.28]):
use
имяНовое
for имениСтарого [, ...]
in класс
Можно заменять имена типов, величин, переменных, объектов
и каналов;
• hide in – инкапсуляция имен (см. [12, стр.28]);
• with in – использование имен объектов по умолчанию (аналог
using namespace) (см. [12, стр.28]);
agp1.fmsd 1.02.10
2.5.8
115
Схемы с параметрами
Схема с параметрами:
---- File:./src/rsl/db.rsl
--//ELEM
scheme DB(D : class type Elem end, R : class type
class
type
Domain = D.Elem,
Range = R.Data,
Database = Domain -m-> Range
end
Data end) =
---- End Of File:./src/rsl/db.rsl
Использование схемы с параметрам применяется при переходе от
аппликативного абстрактного стиля к императивному конкретному:
---- File:./src/rsl/dbuse.rsl
DB
scheme DBUSE = class
object
domain: class type Elem = Int end,
range: class type Data = Text end,
database: DB(domain, range)
end
---- End Of File:./src/rsl/dbuse.rsl
2.5.9
Пример спецификации проекта Гавань
Пример спецификации взят из [2] перевод см. [13]. Спецификация
сначала выполняется в абстрактном стиле. Под абстрактностью понимается такое свойство спецификаций, при которых остается так
много открытых альтернативных путей разработки как возможно.
Другими словами, чем меньше решений проектирования внесено в
спецификацию тем она более абстрактной она будет. Под решениями проектирования мы понимаем вещи вроде таких
agp1.fmsd 1.02.10
116
• решения как определить модуль;
• решения о конкретной структуре данных;
• решения о конкретных алгоритмов;
• решения о используемых переменных;
• решения о используемых каналах и образцах обмена информации для использования.
Противоположностью абстрактности есть конкретность. Различия между ними не есть черно - белыми, однако дают возможность
охарактеризовать некоторый модуль, написанный в стиле одной из
трех категорий, как более абстрактный или более конкретный.
• абстрактный аппликативный – модуль содержит абстрактные
типы и сигнатуры функций с аксиомами, а не явные определения функций;
• конкретный аппликативный – модуль содержит конкретные типы и явные определения функций;
• абстрактный императивный – модуль не определяет переменных, зато использует ключевое слово any в описании его доступа. Содержит аксиомы;
• конкретный императивный – модуль содержит определение переменных и явные определения функций;
И опять надо подчеркнуть, что эти различия более относительные, чем абсолютные. Модуль может быть абстрактный в одном
смысле и конкретный в другом. И, естественно, вся спецификация
будет содержать модули сочетающие несколько стилей и две степени
абстракции.
agp1.fmsd 1.02.10
117
2.5.9.1 Цели примера
Пример является простой информационной системой, имеющей
функции изменения данных, опрашивания данных и инвариантные
свойства (условия целостности) которым данные должны удовлетворять. Не выставляется требований к конкурентному (параллельному) доступу.
Рисунок 2.32 – Порт и изменение состояния судна
2.5.9.2 Требования к функциональности системы
Корабли прибывающие (arrive) в порт, будут распределяться по
подходящим свободным причалам или ждать на рейде, до тех пор
пока подходящий причал не станет свободен. Система должна поддерживать следующие функции позволяющие руководителю порта
управлять движение судов в порту:
agp1.fmsd 1.02.10
118
• arrive: зарегистрировать прибытие судна;
• dock: зарегистрировать причаливание судна к причалу;
• leave: зарегистрировать уход судна из порта.
Порт представлен на рисунке 2.32 . Мы предполагаем, что все корабли должны прибыть и ожидать на рейде (in the pool) прежде чем
они могут причалить. Такое изменение состояния судна отражено на
рисунке 2.32.
Рисунок 2.33 – Схема взаимоотношений между объектами порта
2.5.9.3 Начальная постановка задачи
Сначала нужно спросить что является объектами в системе? В требованиях к функциональности упоминались судна (ships), причалы
(berths), рейд (pool) и порт (harbour). С текущей точки зрения можно считать, что порт является фиксированным списком причалов, в
то время, как количество судов на рейде будет меняться. Схема взаимоотношений (связей) между всеми объектами системы отображены
на рис. 2.33.
agp1.fmsd 1.02.10
119
Затем требуется идентифицировать атрибуты объектов и выяснить, какие из них будут меняться динамически. Единственное атрибут у объекта судно, упомянутый в требованиях – это характеристика соответствия или не соответствия (fit) причалу. Можно высосать
из пальца и ввести в рассмотрение такой атрибут как размер (size),
однако на деле достоверно не известно, можно ли по размеру определять соответствие судна причалу. Таким образом, нужно запомнить,
что вероятно существует потребность в функции
---- File:./src/hrb/fits.r
fits : Ship >< Berth -> Bool
---- End Of File:./src/hrb/fits.r
Причем эта функция некоторое время остается не специфицированной, по крайней мере до консультации с экспертом в соответствующей области.
Причалы изменяют свой атрибут в том смысле, что они могут
быть свободными в один момент времени и заняты некоторым судном в другой. Таким образом мы может определить термин заполненность (occupancy) как динамический атрибут. Это предполагает
что причал будет императивным объектом RSL с функциями которые меняют состояние объекта, например, причалить (enter) и покинуть (leave).
Сам порт, похоже, является множеством причалов. Количество
элементов этого множества очевидно фиксировано. Таким образом
можно рассматривать его как массив.
Рейд (pool) с ожидающими суднами будет изменятся динамически, по мере того, как судна будут прибывать (arrive) и причаливать
(dock). Таким образом тут тоже рекомендуется императивный объект RSL c изменяющими его состояние функциям, например, enter и
leave.
Далее, существует выбор того, что можно трактовать как атрибут. Это может быть динамический атрибут положение (location)
agp1.fmsd 1.02.10
120
судна, которое может быть где-то, ожидать на рейде или быть причаленным (docked) к причалу. Можно было бы сделать судна императивным объектом RSL чтобы промоделировать это. Тогда, в случае
если система содержит динамические причалы и рейд, появляется
дублирование информации. Это вызвало бы лишние накладные расходы при изменение обоих объектов (This would cause extra overhead
in changing both objects consistently). Некоторые системы проектируются таким образом – обычно когда количество информации большое, запросы делаются часто и должны быть быстрыми, а изменения
состояния редкие. Однако это опасная практика и для этой системы
более подходящим подходом будет рассматривать систему как причал и множество ждущих на рейде кораблей и вычислять положение
судна в случае необходимости.
Далее, требуется рассмотреть инварианты (свойства, которые всегда выполняются) данных. Такими свойствами будут следующие возможности:
• судно не может быть в двух местах одновременно;
• на причале не может быть более одного судна;
• судно может причалить только к подходящему причалу (fits).
Существует два пути чтобы работать с такими инвариантами. Если возможно, они встраиваются в модель. Если занятость (occupancy)
причала моделируется либо как свободный (vacant) либо как занят
(occupied by(s), где s - судно), в модели становится недопустимой
возможность причаливания более одного судна к причалу. Таким
образом будет гарантирован второй инвариант. Необходимо также
заметить, что нельзя пытаться причалить судно к причалу, если причал уже занят, однако такая ситуация будет обрабатываться отдельно. напомним, что множество причалов в примере никогда не меняется. Это условие также рассматривается как инвариант.
Первый инвариант задается императивным предикатом
---- File:./src/hrb/inv.r
agp1.fmsd 1.02.10
121
all s: Ship :- ~(waiting(s) /\ is_docked(s)) /\
(all b1, b2: Berth :occupancy(b1) = occupied_by(s) /\
occupancy(b2) = occupied_by(s) =>
b1 = b2
) /\
(all b: Berth :- occupancy(b) =
occupied_by(s) => fits(s,b) )
---- End Of File:./src/hrb/inv.r
Далее, в начальной спецификации будет использован абстрактный тип для порта (harbor). Чтобы указать инвариантное свойство
отраженное предикатом consistent, можно использовать подтип как
в следующем примере
---- File:./src/hrb/hrb.r
type
Harbour_base,
Harbour = {| h: Harbour_base :- consistent(h) |}
---- End Of File:./src/hrb/hrb.r
Эта возможность может быть использована, при генерирование условий доверия (confidence conditions) (см. секцию 4.1.2 [33] ) для конкретной аппликативной спецификации (когда будет построен некоторый конкретный тип Harbour base). С другой стороны очень легко
создать конкретную аппликативную спецификацию, которая выдержит проверку соответствия (implementation check) абстрактной, но
не будет поддерживать выполнения инвариантов, и таким образом
не будут выполнятся условия целостности (inconsistent). Это общее
правило, что подтипы абстрактных типов не должны использоваться до тех пор, пока не будут выведены и проверены условия доверия
(confidence conditions) для конкретных модулей.
Вместо этого, свойство ’изменяющие состояние функции поддерживают инварианты’ будет выражаться набором аксиом. Такой подход делает свойства более видимыми и будет заставлять нас доказывать что они выполняются при проверки реализации (which makes
agp1.fmsd 1.02.10
122
the property more visible and will force us to justify it when we justify
implementation). Может для этого примера это не кажется слишком
важным, но в других примерах (см.[33]) оказывается, что свойства
безопасности выглядят как инварианты.
Например, если arrive это изменяющая состояние функция и consistent
предикат выражающий инвариант, то можно записать аксиому
---- File:./src/hrb/axiom.r
axiom
[arrive_consistent]
all s: Ship :arrive (s) post consistent()
pre consistent() /\ can_arrive(s)
---- End Of File:./src/hrb/axiom.r
где can arrive это предикат выражающий предусловия для arrive.
Теперь получена некая картину объектов в системе. Мы можем
изобразить их как на схеме 2.34 причем там показаны только изменяющие состояние функции. Вообще говоря, хорошей идеей является
попробовать написать сначала одну схему без компонент, так что бы
она наиболее полно удовлетворяла требованиям. А затем произвести
декомпозицию модели.
Как альтернативный путь, можно сначала выполнить декомпозицию системы, чтобы лучше понять, как система будет работать вместе и, возможно, создав абстракцию позже. Как уже было отмечено
раньше, опыт использования RAISE советует что конструирование
более конкретной и структурированной системы, вообще говоря, является более успешной техникой.
agp1.fmsd 1.02.10
123
Рисунок 2.34 – Объекты порта
2.5.9.4 Краткий план разработки
Разработка спецификации будет изменяться от аппликативного к
императивному описанию. Таким образом практически метод будет
использоваться как показано ниже:
• Определить схему TYPES содержащую типы и атрибуты для
не динамических сущностей и сделать глобальный объект T
для этой схемы;
• Определить абстрактный аппликативный модуль A HARBOUR0
содержащий функции высшего уровня, аксиомы, связывающие
их и инварианты;
• Разработать последовательность конкретных аппликативных
модулей:
A HARBOUR1, A HARBOUR2, и т.д., которые будут реализовывать аппликативный модуль для компонент pool и berths;
• Разработать набор соответствующих императивных модулей начиная с последних аппликативных;
agp1.fmsd 1.02.10
124
• Продумать любые улучшения производительности, которые могут быть сделаны в императивных модулях;
• Транслировать императивные модули в язык программирования.
Этот план для конкретных приложений мы будем назвать планом разработки (development plan). На практике такие планы будут
включать некоторое число других действий для документирования,
тестирования, проверке качества (quality assurance) и т.д.
Итак, из начальных размышлений можно сформулировать модуль TYPES:
---- File:./src/hrb/types.rsl
scheme
TYPES =
class
type
Ship,
Berth,
Occupancy == empty | occupied_by(occupant : Ship),
Index = {| i : Int :- i >= min /\ max >= i |}
value
min, max : Int,
fits : Ship >< Berth -> Bool,
indx : Berth -> Index
axiom
[index_not_empty] max >= min,
[berths_indexable]
all b1, b2 : Berth :- indx(b1) = indx(b2) => b1 = b2
end
---- End Of File:./src/hrb/types.rsl
Далее, формулируется понятие целостности специфицируемой системы, которое выражается в виде предиката. Метод вкратце:
agp1.fmsd 1.02.10
125
• Определить название проектируемого типа интереса (Define the
type of interest as a sort – Harbour). В спецификации ниже это
тип, который обозначается словом type. Про его содержимое
ничего не известно;
• Определить сигнатуры необходимых функций;
• Определить эти функции как функции состояния (generator),
если тип интереса (или тип зависящий от него) появляется в
типе результата; или как функции выхода (observer) в другом случае. (Забегая вперед, скажем, что императивная версия
функций состояния есть функция, которая меняет состояние).
В проекте оказывается три функции состояния: arrives, docks,
leaves; и две функции выхода: wainting и occupancy;
• Сформулировать предусловия (precondition) которые должны
выполняться для каждой частичной функции. Все три функции состояния (генераторы) нашего примера являются частичными: существуют ситуации, когда их нельзя применять. Для
этих ситуаций зададим функции защиты (guard) чтобы выразить это предусловия : can arrive, etc. Все функции защиты
должны быть выведены (то есть, им можно дать конкретное
определение в терминах функций выхода) из функций выхода;
• Определить функцию целостности (consistent) типа, делая её
еще одной выводимой функций состояния;
• Для каждой возможной пары не выводимой функции состояния и не выводимой функции выхода определить аксиому, выражающую отношение между ними. Так как мы имеем три не
выводимых функции состояния и две не выводимых функции
выхода, то получаем шесть таких аксиом;
• добавить аксиомы выражающие представление о том, что не
выводимые функции перехода поддерживают целостность типа. Добавляются три такие аксиомы;
agp1.fmsd 1.02.10
126
• Инкапсулировать функцию целостности типа (consistent) и все
то, в чем не нуждаются клиенты модуля.
В результате получится аппликативная спецификация проекта
Гавань в стиле LaTex-а :
Листинг 2: Проект Гавань
T
scheme A_HARBOUR0 =
hide
consistent
in c l a s s
type Harbour
value
/∗ g e n e r a t o r s ∗/
∼
a r r i v e s : T. Ship × Harbour → Harbour ,
∼
docks : T. Ship × T. Berth × Harbour → Harbour ,
∼
l e a v e s : T. Ship × T. Berth × Harbour → Harbour ,
/∗ o b s e r v e r s ∗/
w a i t i n g : T. Ship × Harbour → Bool ,
occupancy : T. Berth × Harbour → T. Occupancy ,
/∗ d e r i v e d ∗/
c o n s i s t e n t : Harbour → Bool
consistent (h) ≡
( ∀ s : T. Ship ∙
∼ ( w a i t i n g ( s , h ) ∧ Is_docked ( s , h ) ) ∧
( ∀ b1 , b2 : T. Berth ∙
occupancy ( b1 , h ) = T. occupied_by ( s ) ∧
occupancy ( b2 , h ) = T. occupied_by ( s ) ⇒
b1 = b2
) ∧
( ∀ b : T. Berth ∙
occupancy ( b , h ) = T. occupied_by ( s )
⇒ T. f i t s ( s , b )
)
agp1.fmsd 1.02.10
127
),
Is_docked : T. Ship × Harbour → Bool
Is_docked ( s , h ) ≡
( ∃ b : T. Berth ∙ occupancy ( b , h ) = T. occupied_by ( s ) ) ,
/∗ guards ∗/
c a n _ a r r i v e : T. Ship × Harbour → Bool
c a n _ a r r i v e ( s , h ) ≡ ∼ w a i t i n g ( s , h ) ∧ ∼ Is_docked ( s , h ) ,
can_dock : T. Ship × T. Berth × Harbour → Bool
can_dock ( s , b , h ) ≡
waiting ( s , h) ∧
∼ Is_docked ( s , h ) ∧ occupancy ( b , h ) = T. empty ∧
T. f i t s ( s , b ) ,
can_leave : T. Ship × T. Berth × Harbour → Bool
can_leave ( s , b , h ) ≡ occupancy ( b , h ) = T. occupied_by ( s )
axiom
[ waiting_arrives ]
∀ h : Harbour , s1 , s2 : T. Ship ∙
w a i t i n g ( s2 , a r r i v e s ( s1 , h ) ) ≡
s1 = s2 ∨ w a i t i n g ( s2 , h )
pre c a n _ a r r i v e ( s1 , h ) ,
[ waiting_docks ]
∀ h : Harbour , s1 , s2 : T. Ship , b : T. Berth ∙
w a i t i n g ( s2 , docks ( s1 , b , h ) ) ≡
s1 ̸= s2 ∧ w a i t i n g ( s2 , h )
pre can_dock ( s1 , b , h ) ,
[ waiting_leaves ]
∀ h : Harbour , s1 , s2 : T. Ship , b : T. Berth ∙
w a i t i n g ( s2 , l e a v e s ( s1 , b , h ) ) ≡ w a i t i n g ( s2 , h )
pre can_leave ( s1 , b , h ) ,
[ occupancy_arrives ]
∀ h : Harbour , s : T. Ship , b : T. Berth ∙
occupancy ( b , a r r i v e s ( s , h ) ) ≡ occupancy ( b , h )
pre c a n _ a r r i v e ( s , h ) ,
[ occupancy_docks ]
∀ h : Harbour , s : T. Ship , b1 , b2 : T. Berth ∙
agp1.fmsd 1.02.10
end
2.6
128
occupancy ( b2 , docks ( s , b1 , h ) ) ≡
i f b1 = b2 then T. occupied_by ( s )
e l s e occupancy ( b2 , h ) end
pre can_dock ( s , b1 , h ) ,
[ occupancy_leaves ]
∀ h : Harbour , s : T. Ship , b1 , b2 : T. Berth ∙
occupancy ( b2 , l e a v e s ( s , b1 , h ) ) ≡
i f b1 = b2 then T. empty e l s e occupancy ( b2 , h ) end
pre can_leave ( s , b1 , h ) ,
[ consistent_arrives ]
∀ h : Harbour , s : T. Ship ∙
a r r i v e s ( s , h ) as h ′
post c o n s i s t e n t (h ′ )
pre c o n s i s t e n t ( h ) ∧ c a n _ a r r i v e ( s , h ) ,
[ consistent_docks ]
∀ h : Harbour , s : T. Ship , b : T. Berth ∙
docks ( s , b , h ) as h ′
post c o n s i s t e n t (h ′ )
pre c o n s i s t e n t ( h ) ∧ can_dock ( s , b , h ) ,
[ consistent_leaves ]
∀ h : Harbour , s : T. Ship , b : T. Berth ∙
l e a v e s ( s , b , h ) as h ′
post c o n s i s t e n t (h ′ )
pre c o n s i s t e n t ( h ) ∧ can_leave ( s , b , h )
Утилита RSLTC – не только проверка синтаксиса
Кроме проверки синтаксиса и частичной статической проверки соответствия типов утилита RSLTC может быть использована для получения условий уверенности ([6, p.8]) и проверки реализация класса.
То есть, проверки соответствия более конкретного класса более абстрактному.
agp1.fmsd 1.02.10
2.6.1
129
Условия уверенности
Условия уверенности – это условия (confidence condition), которые
обычно должны быть истинными на протяжении работы приложения, если модуль удовлетворяет условиям целостности (то есть, не
является противоречивым, inconsistent), но которые, как правило, не
могут быть определены как истинные с помощью утилиты RSLTC
(см. [6, стр.8-11],[39, Схема проверки реализации]). Условия уверенности обращают внимание на потенциальные логические ошибки и
это можно использовать при тестировании.
Для вывода условий уверенности используются ключи -с и -cc:
rsltc -c <file> : Type check plus confidence condition generation on current module
rsltc -cc <file> : Type check plus confidence condition generation on all modules
При обнаружении ошибок условия уверенности не проверяются. Утилита вырабатывает следующие условия уверенности в случаях:
• Аргументы вызовов функций и операторов принадлежат подтипам, в случае частичных функций и операторов пред- условия выполняются.
• Значения, которые должны принадлежать подтипам, им принадлежат. Условия генерируются для:
– значений в явных определениях значений;
– значений явных определений функций (для параметров
в соответствующих подтипах и удовлетворяющих любым
заданным предварительным условиям);
– начальных значений переменных;
– значений, назначенных переменным;
– значений, выводимых в каналы.
• Подтипы не пусты.
agp1.fmsd 1.02.10
130
• Значения, которые удовлетворяют ограничениям, существуют
для неявно определенных значений и функций.
• В случае, когда классы фактических параметров схемы реализуют классы формальных параметров.
• Для отношения или выражения реализации, реализующий класс
корректен (таки реализует то, что надо).
• При определении частичной функции без предусловия.
• При определении всюду определенной функции с предусловием.
В качестве примера рассмотрим следующую схему (для которой все
условия уверенности будут ложными) с намеренно сделанными ошибками:
---- File:./src/rsl/cc/cc.rsl
scheme CC = class
value
x1 : Int = hd <..>,
x2 : Int = f1(-1),
x3 : Nat = -1,
f1 : Nat -~-> Nat
f1(x) is -x
pre x > 0
variable
v : Nat := -1
channel
c : Nat
value
g : Unit -> write v out c Unit
g() is v := -1 ; c!-1
type
None = {| i : Nat :- i < 0 |}
value
x4 : Nat :- x4 < 0,
f2 : Nat -> Nat
f2(n) as r post n + r = 0
end
---- End Of File:./src/rsl/cc/cc.rsl
-- 1
-- 2
-- 3
-- 4
-- 5
-- 6
-- 7
-- 8
-- 9
-- 10
-- 11
-- 12
-- 13
-- 14
-- 15
-- 16
-- 17
-- 18
-- 19
-- 20
-- 21
-- 22
agp1.fmsd 1.02.10
131
Её проверка с ключом ’-c’ приведет к генерации следующих условий
уверенности:
cc.rsl:3:18: CC:
-- application arguments and/or precondition
let x = <..> in x ~= <..> end
Третья строчка схемы явно проблемная. Нельзя взять голову пустого
списка.
cc.rsl:4:17: CC:
-- application arguments and/or precondition
-1 >= 0 /\ let x = -1 in x > 0 end
В функцию f1, входной параметр x у которой по предусловию должен быть больше или равен нулю, передается -1.
Далее, в пятой строке внимание обращается на попытку определить x3 – значение натурального типа как −1:
cc.rsl:5:13: CC:
-- value in subtype
-1 >= 0
Начиная с седьмой строка содержится неправильно определенная
функция f1:
cc.rsl:7:4: CC:
-- function result in subtype
all x : Nat :- (x > 0 is true) => -x >= 0
По определению функции изменение знака любого ненулевого аргумента (большего чем 0) приводит к противоречию.
В десятой и пятнадцатой строках переменной v натурального типа присваивается начальное значение −1:
cc.rsl:10:13: CC:
-- initial value in subtype
-1 >= 0
cc.rsl:15:17: CC:
-- assigned value in subtype
-1 >= 0
agp1.fmsd 1.02.10
132
Кроме того, в пятнадцатой строке в канал выводится (’выводится; –
это текст ’c!−1’, символ операции – восклицательный знак) значение
не подходящего типа:
cc.rsl:15:24: CC:
-- output value in subtype
-1 >= 0
Семнадцатая строка содержит противоречивое определение пустого
типа:
cc.rsl:17:26: CC:
-- subtype not empty
exists i : Nat :- i < 0
В девятнадцатой строке содержится противоречивое неявное определение величины x4 натурального типа:
cc.rsl:19:8: CC:
-- possible value in subtype
exists x4 : Nat :- x4 < 0
Двадцать первая строка содержит противоречивое постусловие. Согласно которому сумма двух натуральных чисел равняется нулю:
cc.rsl:21:5: CC:
-- possible function result in subtype
all n : Nat :- exists r : Nat :- n + r = 0
2.6.2
Проверка реализации класса
В случае реализации отношений и условий к условию уверенности
дописывается тест ’IC:’ (что указывает на условие реализации) и
некоторый комментарий. Сама проверка реализации класса выполняется при помощи модуля с разделом theory. В этом разделе можно записывать утверждения о том, что одна схема реализует вторую
схему. Кроме проверки синтаксиса утилита RSLTC может проверить
это утверждение и обнаружить какие функции, типы и константы
были реализованы, а какие – нет, а так же, какие были реализованы
с изменениями.
Например, пусть начальная схема имеет такой вид:
agp1.fmsd 1.02.10
133
---- File:./src/rsl/theory/a0.rsl
scheme a0 = class
value
x: Int
, z : Int = 2
end
---- End Of File:./src/rsl/theory/a0.rsl
Схема её реализации:
---- File:./src/rsl/theory/a1.rsl
scheme a1 = class
value
x : Int = 1
, z : Int = 3 -- изменена
end
константа
---- End Of File:./src/rsl/theory/a1.rsl
Утверждение о реализации:
---- File:./src/rsl/theory/a_th.rsl
a0, a1
theory a_TH:
axiom
|a1 {= a0
end
---- End Of File:./src/rsl/theory/a_th.rsl
Результат проверки:
rsltc version 2.5 of Sun Jan 9 20:23:27 2005
a_th.rsl:4:18: CC:
-- implementation conditions:
in a1 |-- a1.rsl:4:8: IC: value definition changed
z = 2
rsltc completed: 1 confidence condition(s) generated
rsltc completed: 0 error(s) 0 warning(s)
agp1.fmsd 1.02.10
2.6.2.1 Изменение описания функции
Начальная схема:
---- File:./src/rsl/theory/b0.rsl
scheme b0 = class
value
f: Int -> Int
end
---- End Of File:./src/rsl/theory/b0.rsl
Схема её реализации:
---- File:./src/rsl/theory/b1.rsl
scheme b1 = class
value
f: Int -> Real -- изменен прототип функции
end
---- End Of File:./src/rsl/theory/b1.rsl
Утверждение о реализации:
---- File:./src/rsl/theory/b_th.rsl
b0, b1
theory b_TH:
axiom
|b1 {= b0
end
---- End Of File:./src/rsl/theory/b_th.rsl
Результат проверки:
rsltc version 2.5 of Sun Jan 9 20:23:27 2005
Checking b_TH ...
b_th.rsl:4:18: Value identifier f with expected type Int -> Int not found
Finished b_TH
Errors found, so confidence conditions cannot be generated
rsltc completed: 0 confidence condition(s) generated
rsltc completed: 1 error(s) 0 warning(s)
134
agp1.fmsd 1.02.10
2.6.2.2 Изменение описания типа
Начальная схема:
---- File:./src/rsl/theory/c0.rsl
scheme c0 = class
type
T1, T2 = Nat
end
---- End Of File:./src/rsl/theory/c0.rsl
Схема её реализации:
---- File:./src/rsl/theory/c1.rsl
scheme c1 = class
type
T1 = Text,
T2 = Int
end
-- заменено описание типа T2
---- End Of File:./src/rsl/theory/c1.rsl
Утверждение о реализации:
---- File:./src/rsl/theory/c_th.rsl
c0, c1
theory c_TH:
axiom
|c1 {= c0
end
---- End Of File:./src/rsl/theory/c_th.rsl
Результат проверки:
c_th.rsl:4:18: CC:
-- implementation conditions:
in c1 |-- c1.rsl:4:9: IC: type definition changed
{x_ | x_ : T2} = {x_ | x_ : Nat}
rsltc completed: 1 confidence condition(s) generated
rsltc completed: 0 error(s) 0 warning(s)
135
agp1.fmsd 1.02.10
136
2.6.2.3 Пропущенная функция в реализации
В разделе выполняется статическая проверка реализации спецификации арифметики Пеано. Три спецификации арифметики были
представлены в разделах 2.5.5 и 2.5.6.7: a peano0, a peano1, c peano1.
Следующая схема предназначена для статической проверки корректности обеих реализаций:
---- File:./src/rsl/peano/a_th.rsl
a_peano0, a_peano1, c_peano1
theory a_TH:
axiom
[a0_a1]
|- a_peano1 {= a_peano0,
[a1_ac]
|- c_peano1 {= a_peano1
end
---- End Of File:./src/rsl/peano/a_th.rsl
Статическая проверка схем выполняется командой:
rsltc32.exe
a_th.rsl
Результат выполнения проверки:
rsltc version 2.5 of Sun Jan 9 20:23:27 2005
Checking a_peano0 ...
Finished a_peano0
Checking a_peano1 ...
Finished a_peano1
Checking c_peano1 ...
Finished c_peano1
Checking a_TH ...
a_th.rsl:5:21: Value identifier sum is not implemented
Finished a_TH
rsltc completed: 1 error(s) 0 warning(s)
Функция sum намеренно не была реализована для демонстрации возможностей утилиты.
Таким образом, абстрактная аппликативная схема выполняет роль
заголовочных файлов у компиляторов С++, она может служить руководством для пользователей модуля и разработчиков тестов для
agp1.fmsd 1.02.10
137
модуля. В декларации test case можно записывать тестовые варианты для дымового тестирования, разработанные по методу черного
ящика. Конкретную аппликативную схему можно дополнять тестовыми вариантами, разработанными по методу белого ящика с учетом
критериев покрытия кода (см. [82]).
2.6.3
Генерация зависимости модулей спецификации
В заключение отметим, что ключ ’-d’ (см.2.5.1.1) позволяет отобразить зависимость модулей. Например, для рассмотренной спецификации арифметики Пеано зависимость модулей оказывается такой:
rsltc version 2.5 of Sun Jan
a_TH
a_peano0
a_peano1
c_peano1
9 20:23:27 2005
3
ЛАБОРАТОРНЫЙ ПРАКТИКУМ
3.1
Состояние конечного автомата
Цель:
Для одного из окон (’Ввод данных’, ’Быстрый выбор’, ’Отношение один-ко-многим’, ’Табличные данные’ см.[77, 66, 76]) нарисовать диаграмму состояние конечного автомата. (см. [46]).
Задание:
• В явной форме включить в диаграмму реакцию ПО на
корректный и не корректный ввод данных пользователя;
• По крайней мере, две диаграммы подключить к отчету,
построенному любой программой (MS Word или LaTex,
по желанию) ;
agp1.fmsd 1.02.10
138
• В отчете использовать двойную нумерацию рисунков (номер раздел + номер рисунка в разделе) и ссылки на диаграммы.
• Разработать приложение с имитацией описанного окна.
• Окно ’Ввод данных’ можно взять из драйвера тестов [29].
• Для усложненной версии – написать диаграмму окна на
языке пакета визуализации графов GraphViz (см. 2.1.3).
3.2
Отчет для Doxygen
Тема:
Doxygen и диаграммы классов
Цель:
Из любой курсовой работы построить построить пояснительную записку в формате компрессированного HTML.
Задание:
• Получить отчет по любому проекту в виде справочного
файла Микрософта c расширением .chm;
• Отчет должен содержать иерархию классов проекта в виде UML диаграммы.
• Повторить иерархию классов на UML диаграмме с обозначениями Б.Мейера [60, Введение в наследование].
• Добавить UML диаграмму проекта с потоками данных.
agp1.fmsd 1.02.10
3.3
139
Первый отчет для LaTex
Тема:
Система компьютерной верстки LaTex
Цель:
Написать первый отчет и построить выходной документ LaTexа ом.
Задание:
• На стандартной странице A4 использовать отступы для
технических отчетов ДСТУ: слева – 2.5cm, справа – 1cm,
сверху – 2cm, снизу – 2cm.
• В отчет добавить 8 требований к приложению из своего
диплома или курсовой, с характеристикой его качества.
Примеры см. [86, стр.32] и [86, стр.54].
• Использовать библиографию: набрать отдельный файл со
списком цитированных документов и подключить его к
отчету.
• Использовать предметный указатель - список терминов.
• Подключить файл с изображением.
• В отчет подключить не форматируемый текст (код любой
программы).
3.4
Иерархия классов .Net
Тема:
UML - диаграммы и проектирование по контракту
agp1.fmsd 1.02.10
140
Цель:
Построить иерархию (исключительных состояний или классов,
предоставляющих данные для событий (наследники EventArgs),
или зависимость конкретных классов ADO провайдера SQLite3
от абстрактного или потоков данных Stream) в терминах Б.Мейера.
Задание:
• Иерархия должна иметь хотя бы четыре уровня наследования.
• В диаграмме показать около 14 знакомых классов. Для
исключительных состояний должны быть наследники AriphmeticExcept
IOException, ArgumentExcepyion, FormatException которые часто встречаются при разработке приложений.
• Эффективные (то есть, реализованные) поля и методы
отмечать в иерархии.
• Как дополнительное условие, диаграмму строить средствами пакета визуализации графов GraphViz.
• Способ ориентации графа должен предусматривать удобное расположение на странице A4.
3.5
Требования к данным
Тема:
Требования к данным и Формы Бекуса-Наура
Цель:
Описать синтаксис (или упрощенного Си см.[35, Обновленный
agp1.fmsd 1.02.10
141
краткий синтаксис языка Си], или CSV-файла с треком движения летательного аппарата, или входных данных для проекта ’Калькулятор успеваемости’ (см. 3.10.2)). Данные можно
описывать либо языком формальных спецификаций либо при
помощи утилиты визуализации (см. [1]).
Задание:
В случае трека, описание должно содержать:
• координаты текущего положения ЛА в градусах мировой
системы координат (широта, долгота и высота);
• три угла наклона для ЛА (тангаж, заваливание, рыскание);
• момент времени в который фиксировались данные о ЛА;
• естественные ограничения на вещественные и целые числа – диапазон значений, количество знаков после запятой, вид представления времени, вид представления градусов).
Задания [75, Текстовое представление целых чисел] (усложненная
версия [79, ТЕКСТОВОЕ ПРЕДСТАВЛЕНИЕ ВЕЩЕСТВЕННЫХ
ЧИСЕЛ]) – могут служить примером для описания чисел в виде
БНФ.
3.6
Требования к приложению
Тема:
Требования к приложению.
Цель:
Использовать математический режим LaTex для подготовки
технического задания на разработку приложения.
agp1.fmsd 1.02.10
142
Задание:
• Оформление ТЗ выполнять по требованиям национального стандарта для научно-технических отчетов ([51, 30]).
• Использовать многострочные формулы с автоматической
нумерацией и многострочными скобками.
• В формулах использовать буквы греческого алфавита,
нижние и верхние индексы у букв.
• Использовать текст с кириллицей в математическом режиме.
• В явной форме включить в ТЗ спецификацию аксиом
предусловий, постусловий и инвариантов.
• Использовать не менее 10 требований.
• Уделить внимание совместимости, несовместимости, нелогичности, неточности требований для приложения.
• Постановки задач для разрабатываемого приложения можно выбирать из [54].
3.7
Формальная спецификация функции
Тема:
Спецификация языка RSL
Цель:
Записать на языке RSL спецификацию любой лабораторной
или модульной работы из [75, 65].
agp1.fmsd 1.02.10
143
Задание:
• Использовать утилиту проверки синтаксиса (см. [39, 6],
2.5.1).
• Cпецификация должна состоять, по меньшей мере из двух
схем.
• При помощи утилиты проверки синтаксиса (см. 2.5.1) убедиться в отсутствии ошибок.
• Для мелких вспомогательных функций использовать лямбда - выражение.
• Спецификацию желательно разработать в обоих (аппликативном и императивном) стилях. Сравнить рекомендации главы [85, Процесс программирования с псевдокодом]
с аппликативным и императивным стилем спецификаций;
• В отчет включить спецификацию в ASCII - виде.
• Текст отчета должен содержать раздел приложение, оформленное по правилам национального стандарта для научнотехнических отчетов ([51, 30]).
3.8
Формальная спецификация абстрактного типа данных
Цель:
Спецификация абстрактного типа данных (контракт)
Задание:
agp1.fmsd 1.02.10
144
• Использовать в отчете пакеты и настройки для корректного отображения символов языка формальной спецификации (см. 2.5.1).
• В явной форме описать пред- и пост- условия в виде аксиом для типа данных.
• В аксиомах обязательно использовать абстрактный аппликативный стиль записи к попарному применению функций.
• В отчет включить обе версии спецификации: тестовую
версию и версию для LaTex .
3.9
Спецификация приложения
Тема:
Применение на практике
Цель:
Записать спецификацию приложения (для любой курсовой или
решения задач из [54]).
Задание:
Отчет должен содержать:
• Список требований к приложению, не менее дюжины.
• На выбор: либо создать схему потоков данных между
единицами компиляции приложения или диаграмму архитектуры.
• Полностью разделить функциональность и классы для
управления интерфейсом пользователя приложения.
agp1.fmsd 1.02.10
145
• Для двух единиц компиляции или двух классов в явной
форме записать требования к единице компиляции в виде
контракта (домен класса, функции, предусловия и инварианты).
• Для двух единиц компиляции разработать драйвера тестов и описать их командную строку.
• Для каждого из драйверов теста записать по три теста
(CSV- или XML- файлы и параметры командной строки)
и предполагаемые результаты тестирования.
3.10
Экспериментальные лабораторные
3.10.1
Требования к задаче Г.Майерса о треугольниках
Написать на языке формальных спецификаций описание задачи Г.Майерса
о треугольниках см. [49, стр. 20].
3.10.2
Требования и спецификация приложения
’Калькулятор успеваемости’
Цель:
В любой форме выработать список требований и спецификацию приложения ’Калькулятор успеваемости’
Требования
• см. [77, Текущая сводная таблица проекта Калькулятор
успеваемости]
• Входная форма1: список фамилий студентов из CSV- файла.
agp1.fmsd 1.02.10
146
• Входная форма2: список работ: идентификатор, название, признак просто - модуль - экзамен.
• Выходная форма1: Список фамилий для текущего занятия. Одна фамилия – одна строка, первый символ строки
– не пробел.
• Редактирование: символ ’+’ после фамилии означает присутствие на занятии.
строчки, у которой первый символ пробел – означает добавление баллов за выполненную работу: ’ пробел идентификатор работы пробел баллы’.
• Выходная форма2: Итоговая таблица сумма - модуль1 модуль1 - экзамен - фамилия- список оценок за работы.
• Выходная форма3: Посещаемость.
• Выходная форма4: Итого (см.3.10.3).
3.10.3
Требования и спецификация системы Учет успеваемости
Входные данные:
1. предмет;
2. лабораторные, модули, экзамены;
3. специальные задания;
4. группы;
5. студенты;
6. ответы;
7. оценки;
agp1.fmsd 1.02.10
147
8. значения для получения автомата.
Выходные данные:
1. итоговая таблица:
m1
m2
--- --5.2 5.0
3
5.0
3.2 4.4
3.5 6.1
4.3 2.5
4.5 4.5
. . .
2.5 2.5
1
0.1
1
-
test
----
grp
---151a
151a
151b
151a
151a
151b
nm
-----------martynenko
rudyk
matyash
glamazda
davidenko
nikolenko
ball
----74.95
74.1
65.9
52.9
47.0
45.1
151a
151a
151a
golub
zhivolupova
velikiy
25.4
23.2
7
2. задание на модуль (на экзамен) для студента;
3. список сданных работ с оценками;
4. работа с тестами.
3.10.4
Диагональное произведение (соединение) и операторы Чёрча
Тема:
Математический режим LaTex -а
Цель:
Выразить диагональное произведение функций через суперпозицию, примитивную рекурсию и 𝜇 - операцию.
Задание:
agp1.fmsd 1.02.10
148
• Выразить операцию соединение (диагональное произведение функций) через суперпозицию, примитивную рекурсию и 𝜇 - операцию;
• Пронумеровать формулы;
• Использовать библиографию и правильно оформленные
ссылки и практикум [53, стр.42] и монографию [59, стр.20].
Замечание
Диагональное произведение функций удобно использовать при
описании формальных форм в РСУБД (см. [11]) и, что более важно, при определении безопасных форм наследования
в ООП, свободных от нарушения принципа подстановки (см.
[31]).
3.10.5
Полнота спецификации Стека-Очереди
Тема:
Абстрактные типы данных
Цель:
Доказать, что спецификация 2.3.3.1 удовлетворяет правилу первый пришел - первый ушел (в случае очереди), либо первый
пришел - последний ушел (в случае стека).
Задание:
• Доказать корректность спецификации;
• Убедиться в полноте спецификации;
• Доказательство в математическом режиме LaTex-а включить в отчет.
agp1.fmsd 1.02.10
3.10.6
149
Доклад по не обсужденным и новым возможностям Doxygen
Цель:
Обновление отчета (см.[69])
3.10.7
Требования и спецификация системе Тестирование работ
Входные данные:
• код работы генерировать из Фамилии, группы и номера работы;
• исходный текст работы;
• драйвер теста;
• входные данные для тестов;
• эталонный результат выполнения тестов;
• выполнение тестов: тестировщик, дата, компилятор код работы, код теста, результат;
Выходные данные:
1. код работы, код теста, результат тестирования (опционально
входные данные теста);
2. для отрицательно завершенных тестов выдать текст программы, текст драйвера теста, входные данные теста, результаты
выполнения теста.
3.10.8
Описание и Реализация типа Арифметика Пеано
Выполняется в рамках работы [31].
agp1.fmsd 1.02.10
3.11
Вопросы
3.11.1
Первая группа вопросов
150
1. Что такое принцип самодокументирования и где он реализован?
2. Что такое формальная спецификация и для чего она нужна?
3. Что такое принцип самодокументирования и зачем он нужен?
4. Что такое абстрактный стиль спецификации?
5. Что такое прототипирование?
6. Неявные и явные спецификации, их отличия и особенности.
7. Аппликативный и императивный стиль спецификации.
8. Сравнить рекомендации главы [85, Псевдокод для профи] с аппликативным и императивным стилем спецификаций.
9. Что такое потоки данных и как их используют?
10. Определения требований и их содержание.
11. Характеристики качественного требования.
12. Нотация Б.Мейера для иерархии наследования.
13. Найти определение типа в [46];
14. Найти определение класса в [46] (в конце второй главы есть
вопрос что такое объекты и классы, то есть подразумевается,
что уже все понятно, то есть, границы поиска до конца второй
главы :));
15. Что такое абстрактный тип данных?
agp1.fmsd 1.02.10
151
16. Категории функций абстрактного типа данных и их связь методами реализованного класса.
17. Полнота спецификации, достаточная полнота спецификации,
18. Категоричность спецификации, наследование категоричных спецификаций.
19. Минимальные виды наследования.
20. Языки, которые можно трактовать как языки спецификаций.
21. Что такое абстрактный автомат?
22. Основные диаграммы языка UML и их особенности.
23. UML - диаграммы потоков данных.
24. UML - диаграммы состояний.
25. Отличия диаграммы состояний от диаграммы автомата.
26. Из чего состоят блок-схемы.
27. UML - диаграммы иерархии классов.
28. Схемы реляционных связей РСУБД.
29. Что такое БНФ и его применение.
30. Базовые команды doxygen.
31. Требования и их классификация.
32. Пользовательские требования к приложению. измеряемые, не
измеряемые, но допускающие объективный контроль не измеряемые и не допускающие объективный контроль.
33. Требования к приложению и типы данных.
agp1.fmsd 1.02.10
152
34. Ошибки, дефекты, отказы в ПО.
35. Показать, что спецификация стека соответствует определению
абстрактного автомата.
36. Показать, что аксиоматика Пеано соответствует спецификации
абстрактного класса в терминах Б.Мейера.
37. Хвостовая рекурсия. Примеры рекурсивных алгоритмов в виде
хвостовой и не хвостовой рекурсии.
3.11.2
Вторая группа вопросов
1. Статическая типизация и проверка синтаксиса текста спецификации.
2. Язык формальных спецификаций RSL: Схемы языка и общая
структура спецификации.
3. Язык формальных спецификаций RSL: схемы с состоянием, изменение состояния.
4. Спецификация функций с циклами без конструкций для циклов.
5. Утилита проверки синтаксиса RSLTC, её использование, ключи
командной строки.
6. Встроенные типы языка RSL, операции над выражениями встроенных типов.
7. Прямые произведения языка RSL и выражение let.
8. Язык формальных спецификаций RSL: Введение новых типов.
9. Язык формальных спецификаций RSL: описание констант.
10. RSL: описание переменных, локальных переменных, конструкции для циклов.
agp1.fmsd 1.02.10
153
11. Язык формальных спецификаций RSL: логические выражения.
12. Язык формальных спецификаций RSL: способы описания функций.
13. Язык формальных спецификаций RSL: в аппликативном абстрактном стиле описать требования к одной из пар функций:
знак числа и модуль числа; синус и косинус; извлечение квадратного корня и возведение в степень; отображение градусов в
радианы и наоборот; экспоненциальная функция и логарифм;
тангенс и котангенс; и т.д.
14. Язык формальных спецификаций RSL: описание множеств, операции над множествами.
15. Язык формальных спецификаций RSL: описание списков, операции над списками.
16. Язык формальных спецификаций RSL: описание прямых произведений, записи, операции над прямыми произведениями.
17. RSL: выражение case и списки.
18. Язык формальных спецификаций RSL: описание отображения,
операции над отображениями.
19. RSL: вариантные определения (перечисления).
20. RSL: расширение схем (наследование).
21. Язык формальных спецификаций RSL: схемы с абстрактными?
типами (шаблоны).
22. Язык формальных спецификаций RSL: лямбда выражения.
23. Определить подтип всех нечетных целых чисел.
24. Определить подтип всех вещественных чисел от -1.0 до 1.0.
agp1.fmsd 1.02.10
154
25. Написать выражение для выражения следующего факта: нет
наибольшего целого числа.
26. Написать выражение для выражения следующего факта: натуральное число n является четным числом.
27. Формально записать определение всюду определенной функции.
28. Определить тип для представления всех точек с целочисленными координатами, лежащими внутри круга с центром в начале
координат и радиусом 5.
29. Определить функцию, которая проверяет является ли её аргумент простым числом.
30. Определить множество, элементами которого являются простые числа в диапазоне от 2 до 30.
31. Определить функцию для сортировки элементов заданного списка.
32. Определить список, элементами которого являются числа Фибоначчи, не превосходящие 1000.
33. Определить функция для вычисления максимального элемента
конечного списка из вещественных чисел.
34. Определить отображение, сопоставляющее каждому нечетному натуральному числу, не превосходящему 30, его остаток от
деления на 3.
35. Определить отображение, сопоставляющее каждой координате
всемирной системе координат 84 координату пикселя на экране
800x600.
agp1.fmsd 1.02.10
4
ПРИМЕРЫ
4.1
Преамбула настоящего документа
155
Текущий документ был построен при помощи следующей преамбулы:
---- File:./tmain.tex
%
\documentclass[14pt,a4paper,oneside]{extarticle}
% \usepackage{mathptmx}
%% почти таймньюроман
\renewcommand{\rmdefault}{ftm}
%\documentclass[a4paper,oneside]{report}
%% страница a4, кегль 10, с одной стороны бумаги, статья
% отчет делится на главы, потом на секции, статья делится на секции и подсекции
% для дипломов
%\documentclass[a4paper,oneside]{extreport}
%\usepackage{vmargin}
%\setmarginsrb{2.5cm}{2cm}{1.5cm}{2cm}
%\setmarginsrb{2.5cm}{2cm}{1.5cm}{2cm}{0pt}{0mm}{0pt}{13mm}
\indentfirst % отступ в первом абзаце
\usepackage{verbatim}
\usepackage{makeidx}
\usepackage[dvips]{graphicx}
\usepackage[cp1251]{inputenc} %% кодировка входного файла 1251
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage[russian]{babel} %% русские служебные слова -- список литературы
\usepackage{cmap}
%% правильный поиск слов кирилицы в Acrobat Reader
%
%% \usepackage{times}
%\usepackage{fancyhdr}
\usepackage{multicol}
\usepackage{textcomp}
\usepackage{alltt}
\usepackage{framed}
%%%\usepackage{xcolor}
\usepackage{float}
% определяет размер картинок -- надо!
\setcounter{secnumdepth}{6}
%% глубина нумерации секций
\setcounter{tocdepth}{5}
%% и попадание в оглавление
\renewcommand{\footrulewidth}{0.4pt}
\numberwithin{equation}{section} % Формула вида секция.номер
agp1.fmsd 1.02.10
156
\usepackage{chngcntr}
\counterwithin{figure}{section}
\renewcommand{\thetable}{\thesection.\arabic{table}} % Формат таблицы секция.номер
\makeindex
%% \documentstyle[zed,ztc]{article}
\usepackage{oz,ztc}
%\zedcompatible
пропадает кирилица в оглавлении
:(
\usepackage{rslenv}
\usepackage[pdftex
pagebackref=true,
colorlinks=true,
linkcolor=blue,
unicode=true
]{hyperref}
%% подписи к таблицам и рисунков
\usepackage{caption}
\DeclareCaptionLabelSeparator{defffis}{ ~--~ } % Разделитель
\captionsetup[figure]{justification=centering, labelsep=defffis, format=plain} % Подпись рисунка п
\captionsetup[table]{justification=raggedright, labelsep=defffis, format=plain, singlelinecheck=fa
\DeclareCaptionLabelFormat{gostfigure}{Рисунок #2}
\captionsetup[figure]{labelformat=gostfigure}
\DeclareCaptionLabelFormat{gosttable}{Таблица #2}
%\DeclareCaptionLabelFormat{gosttable}{Таблиця #2}
\captionsetup[table]{labelformat=gosttable}
%% конец подписей
\newcounter{tottables}
\usepackage {listings}
\lstloadlanguages {RSL, SQL, [Sharp]C, C++} % вибiр мов програмування
\lstset{
extendedchars=true
}
\begin{document}
\input {title}
\maketitle
\thispagestyle{empty}
agp1.fmsd 1.02.10
157
\newpage
\setcounter{page}{2}
\pagestyle{myheadings}
\input {.text0}
%% чтение файла, тут чтение файла
.text0.tex
\thispagestyle{myheadings}
\end{document}
%to avoid problem at the end of file
%
%
%
---- End Of File:./tmain.tex
Команды библиографии:
---- File:./biblio.txt
% стиль под гост
%\bibliographystyle{gost780s}
%\bibliographystyle{unsrt}
\bibliographystyle{plain}
% файлы с базами библиографии
% \bibliography{../../bibDB/add,../../bibDB/agp1,../../bibDB/osrc,../../bibDB/smp,../../bibDB/soft
\bibliography{../../usr/add,../../usr/agp1,../../usr/osrc,../../usr/smp,../../usr/soft,../../usr/m
---- End Of File:./biblio.txt
4.2
Примеры спроектированной архитектуры
В разделе исключительно с целью иллюстрации приводятся примеры архитектуры работающей системы [71, Синхронизация каталогов
’HTTP Backup’] и попытки (малоудачной (:) формального изложения
архитектуры интерактивного приложения [72, 73, Проектирование и
декомпозиция двунаправленных потоков данных интерактивных систем], которые разрабатывались согласно идеям Дейкстры (см. рис.
4.1).
agp1.fmsd 1.02.10
158
’HTTP Backup’ передает с компьютера на компьютер через протокол http файлы из БД (собственно сами файлы БД и каталоги
с видеороликами) некоторой информационной системы и служебные файлы (нужные для работы ’HTTP Backup’). Скрипты ’HTTP
Backup’ обращаются друг к другу согласно следующей схемы на
рис.4.1. Уровни абстракции состоят из следующих скриптов, функции некоторых из них перечисляются ниже:
• Первый уровень: mkTran (управление полной передачей (загрузку - выгрузку) данных);
• Второй: wget (загрузить одну передачу данных) и out (выполнить копирование файлов в локальный каталог, создать в нем
служебный файл с командами на удаление файлов – подготовить данные для загрузки удаленной системой. Все такие данные называются ’передача’);
• Третий – ackT (удаление служебных файлов передачи, на которые получен сигнал подтверждения о загрузке), ackF (удаление файлов (тех, которые сохраняются удаленной системой) из
передачи), tran2mfs (загрузка файлов из удаленной системы),
syncDir (синхронизация рабочего каталога БД и ), mfs2tran;
• wGetTran, chkFl, wGetFl (скачивание отдельных частей получаемого файла БД, дешифровка их, сборка исходного файла
БД или видеоролика), inFl, dbBcp, outFl (разделения передаваемого файла из БД на части, шифрование его и создание
служебного файла) ), outTran;
agp1.fmsd 1.02.10
159
Рисунок 4.1 – Архитектура ’HTTP Backup’
Второй пример представляет собой попытку формально описать
на языке RSL совместную работу пользователя интерактивной программы (см. [72, 73]).
agp1.fmsd 1.02.10
160
Рисунок 4.2 – Архитектура интерактивной системы
Название уровней абстракции находятся в крайней левой колонке рисунка. Множество автоматов (приложений), автомат (список
открытых окон со списками разных документов) , состояние (список
документов), документ (список полей), поле.
Задание [76, 64, ЛАБОРАТОРНАЯ РАБОТА: МНОГОДОКУМЕНТНЫЙ ИНТЕРФЕЙС] представляет собой попытку реализации этой
архитектуры.
Для простоты будем считать, что система не меняет своего состояния, пока ждет команды пользователя. То есть, пользователь
и система, являющаяся группой процессов, работают строго последовательно: система получает команду от пользователя, выполняет
agp1.fmsd 1.02.10
161
некоторые действия, выдает результат своей работы пользователю.
Результат работы приложения, кроме всего прочего, включает некоторое множество команд S, из которого пользователь может выбрать
следующую команду и дать ее на выполнение системе. Пользователь
читает результат, выполняет некоторые действия над ним, выдает
следующую команду (выбранную из множества S) для системы. Процессы системы обмениваются с пользователем информацией через
каналы данных. Считается, что пользователь может выбрать команду из множества, которое ему послало приложение. Система всегда
выводит результаты своей работы во все каналы, пользователь читает данные изо всех каналов, а пишет команды только в один канал
или вообще не пишет.
Следующее упорядоченное множество объектов (условное название – линейка масштабирующих объектов) позволяет естественным
образом выделить различные уровни абстракции в описании системы:
1. операционная система (operational system) – множество автоматов (machine set);
2. приложение (application) – автомат (machine);
3. форма (панель, panel) – состояние автомата (state);
4. окно данных (record window) – визуализация множества (set);
5. поле (field) – элемент множества;
Сразу оговоримся, что объект операционная система введен в
рассмотрение только для иллюстрации и законченности описания.
Введенное множество обЪектов позволяет выделить уровни абстракции и, соответственно им, разделить множество программ на
группы (слои) программ. Кроме этого, множество каналов данных
тоже естественным образом разделятся на соответствующие группы
по признаку использования одним из перечисленных обЪектов:
agp1.fmsd 1.02.10
162
• Уровень операционная система (множество автоматов): Операционная система имеет каналы osIn, osOut. В состояние операционной системы включается список работающих приложений.
osIn
через этот канал от пользователя идут команды выбора работающего приложения (следующее, предыдущее),
команда на выполнение заданного приложения, команда
принудительной остановки текущего работающего приложения.
osOut
через этот канал к пользователю идет список допустимых команд (выбрать следующее приложение, выбрать
предыдущее приложение, запустить еще одно приложение, команда принудительного завершения приложения)
и список работающих приложений.
• Уровень приложение (автомат): приложение имеет каналы каналы appIn, appOut. В состояние приложения включается список работающих панелей.
appIn
через этот канал от пользователя идут команды из главного меню приложения, команда завершения приложения, команда принудительного закрытия текущей панели.
appOut
через этот канал к пользователю идет список допустимых
команд ( выбрать следующую панель, выбрать предыдущую панель, принудительно закрыть панель, открыть
еще одну панель) и список работающих панелей для выбора.
agp1.fmsd 1.02.10
163
• Уровень формы (состояние автомата): каналы panIn, panOut.
Формы приложения делятся на группы:
– информационные – без объектов уровня множества;
– табличные панели – используются для просмотра списка
сущностей (не модальные формы).
– панели редактирования – используются для редактирования сущности;
– панели редактирования записи;
Данные, описывающие сущность отображаются на панели через одно или несколько окон визуализации множества (records
window, окно данных) – records window.
К этому уровню относятся:
– команды изменяющие множество сущностей (задаются
кнопками на панели) – удалить, добавить, извлечь, редактировать;
– команды выбора окна визуализации множества: выбрать
следующее окно данных, выбрать предыдущее окно данных.
panIn
через этот канал от пользователя идут команды из множества
PanInput = Add, Delete, Edit, Refresh, Filter, Order, Export,
Exit, Cancel ( Табличные панели имеет все перечисленные
кнопки, а панели редактирования Add, Delete, Edit, Exit)
и команды переключения окон данных.
agp1.fmsd 1.02.10
164
panOut
через этот канал к пользователю идет список допустимых команд из множества PanInput. Заметим, если текущая панель была окном редактирования сущности, то
список команд будет ( Exit, Cancel, Edit, Delete). Если,
текущая панель – окно просмотра таблицы – то список
команд будет равен PanInput.
• Уровень визуализации множества: каналы setIn, setOut. изменение вида множества записей. К набору команд относятся команды изменения вида множества:
– команды сортировки окна данных;
– команды движения курсора по записям и колонкам окна
данных;
– команды движения окна данных по множеству записей
(скроллинг);
setIn
setOut
Кроме того, приложение на этом уровне обменивается данными
с базой данных (или с устройством долговременной памяти).
• Уровень элемента множества: через каналы передаются целые,
вещественные и строковые величины.
itemIn
itemOut
agp1.fmsd 1.02.10
4.3
165
Препроцессор mkTex
На самом деле, текст текущего документа набирался с командами
очень старого (и простого) документатора форматера текста RIO,
который эксплуатировался 30 лет назад. Команды RIO при помощи
препроцессора mkTex переводились в команды LaTex-а (см. [24, 26]):
---- File:./mkpdf.cmd
SET GOAL=text
echo on
call ..\..\params.%COMPUTERNAME%.cmd
echo off
rem SET BIB=..\..\bibDB
SET LATEX=%P%\pdflatex.exe
SET MKIDX=%P%\makeindex.exe
SET BIBTEX=%P%\bibtex.exe
SET PAR=doxygen;class=article;vsize=2;
echo on
copy tmain.tex .%GOAL%.tex
rem препроцессор mkTex
if %1. == 0.
goto one
%MKT% %PAR% <%GOAL%0.rio > .%GOAL%0.tex
%MKT% %PAR% < %GOAL%0FSS.rio > .%GOAL%0FSS.tex
%MKT% %PAR% <%GOAL%00.rio > .%GOAL%00.tex
%MKT% %PAR% <%GOAL%01.rio > .%GOAL%01.tex
%MKT% %PAR% <%GOAL%02.rio > .%GOAL%02.tex
%MKT% %PAR% <%GOAL%0K.rio > .%GOAL%0K.tex
%MKT% %PAR% <%GOAL%03.rio > .%GOAL%03.tex
%MKT% %PAR% <%GOAL%030.rio > .%GOAL%030.tex
%MKT% %PAR% <%GOAL%031.rio > .%GOAL%031.tex
%MKT% %PAR% <%GOAL%032.rio > .%GOAL%032.tex
%MKT% %PAR% <dgIntro.rio > .dgIntro.tex
%MKT% %PAR% <%GOAL%04.rio > .%GOAL%04.tex
%MKT% %PAR% <%GOAL%05.rio > .%GOAL%05.tex
%MKT% %PAR% <%GOAL%0Ex.rio > .%GOAL%0Ex.tex
%MKT% %PAR% <%GOAL%z.rio > .%GOAL%z.tex
%MKT% %PAR% <introZ2.rio > .introZ2.tex
%MKT% %PAR% <doxyCol.rio > .doxyCol.tex
agp1.fmsd 1.02.10
166
%MKT% %PAR% <stateMachine.rio > .stateMachine.tex
rem %MKT% %PAR% <textSPI.rio > .textSPI.tex
.rio
%MKT% %PAR% <%GOAL%SPI.rio > .%GOAL%SPI.tex
%MKT% %PAR% <%GOAL%Pr.rio > .%GOAL%Pr.tex
%MKT% %PAR% <%GOAL%PrQ.rio > .%GOAL%PrQ.tex
rem %MKT% %PAR% <%GOAL%Pr2.rio > .%GOAL%Pr2.tex
%MKT% %PAR% <%GOAL%Hrb.rio > .%GOAL%Hrb.tex
%MKT% %PAR% <adm_aDF1.rio > .adm_aDF1.tex
%MKT% %PAR% <gls.rio > .gls.tex
if %1. == 1.
goto one
%LATEX% -interaction=batchmode
.%GOAL%.tex
%MKIDX%
>.makeindex.log .%GOAL%.idx -o .%GOAL%.ind
%BIBTEX%
.%GOAL%
1>.%GOAL%.bib.log
%LATEX% -interaction=batchmode
.%GOAL%.tex
:one
%LATEX% -interaction=batchmode
exit
---- End Of File:./mkpdf.cmd
.%GOAL%.tex
agp1.fmsd 1.02.10
5
167
СЛОВАРЬ
maplet
- математический символ для обозначения функции
дефект
Дефект (англ. defect) - свойство ПО, которое может стать причиной вычисления результатов, отличных от предполагаемых
в спецификации ( [60]).
инвариант
Инвариант (англ. invariant) - свойства, которыми обладают
все переменные определенного типа ( [60]).
мониторинг
Мониторинг ([60, стр.573]) - находит отказы, но не ошибки
или дефекты.
отказ
Отказ или неисправность (англ. fault) - событие в ПО, которое
привело к вычислению результатов, отличных от предполагаемых в спецификации во время одного из выполнений ПО (
[60]).
ошибка
Ошибка (англ. error) - неверное решение, принятое при разработке ПО ( [60]).
требование
Требование (requirement): Положение, содержащее критерии,
которое должны быть соблюдены (см.[14, 4.1416]).
Предметный указатель
Char, 233
Float, 233
Int, 233
String, 233
any , 116
case, 106
cases, 72
chaos, 96
chapter, 54
dom, 247
end schema, 235
equation, 72
forall, 239
fun, 239
head, 247
if, 105
input, 241
let, 105
local, 110
medskip, 54
paragraph, 54
pow, 96
pred, 275
ran, 247
read, 110
schema, 235
secnumdepth, 54
setcounter, 54
skip, 104, 110
subsection, 54
subsubsection, 54
succ, 275
tableofcontents, 54
tail, 247
test case, 98, 108, 137
theory, 132
tocdepth, 54
until, 111
where, 235, 238
while, 111
write , 110
./biblio.txt , 157
./etc/example.bib, 56
./mkpdf.cmd, 165
./mkpdf.cmd , 58
./pics/comp/exchange1251.dot , 23
./src/ dot/sttmchn/1-m2.dot , 230
./src/ dot/sttmchn/datainput.dot
, 224
./src/ dot/sttmchn/edges.dot , 222
./src/ dot/sttmchn/mainwnd1.dot
, 227
./src/ dot/sttmchn/mainwnd2.dot
, 228
./src/ dot/sttmchn/mainwndred.dot
, 226
./src/ dot/sttmchn/nodes.dot , 221
./src/ dot/sttmchn/okcancel.dot ,
223
./src/ dot/sttmchn/tbl1.dot , 229
./src/bb/bb.zsl, 241
./src/bb/err.lg, 242
168
agp1.fmsd 1.02.10
./src/bowen/g.zsl, 325
./src/csharp/args.txt, 213
./src/csharp/hello., 188
./src/csharp/lib.cs, 187
./src/csharp/main.cs, 186
./src/csharp/main.txt, 49
./src/data/double.zsl, 247
./src/data/int.zsl, 246
./src/data/name.zsl, 244
./src/dttmtoa/dttmto.h , 82
./src/etc/f.zed, 239
./src/etc/f.zsl , 238
./src/etc/z.cmd, 237
./src/etc/z.sed, 237
./src/float/spec2.zsl, 240
./src/hrb/axiom.r, 122
./src/hrb/fits.r, 119
./src/hrb/hrb.r, 121
./src/hrb/inv.r, 121
./src/hrb/types.rsl, 124
./src/intro/axdef.zed, 312
./src/intro/axdef.zsl, 312
./src/intro/gendef.zed, 313
./src/intro/gendef.zsl, 313
./src/intro/syntax.zed, 314
./src/intro/syntax.zsl, 314
./src/intro/text.zed, 311
./src/intro/text.zsl, 311
./src/peano/peano.rsl, 102
./src/rsl/cc/cc.rsl, 130
./src/rsl/choose.rsl, 110
./src/rsl/crvlen1.rsl , 105
./src/rsl/db.rsl , 115
./src/rsl/dbuse.rsl , 115
./src/rsl/factorial.rsl, 112
169
./src/rsl/funcs.rsl, 95
./src/rsl/funcs2.rsl, 96
./src/rsl/getset.rsl, 110
./src/rsl/muller/mlrsec.rsl, 98
./src/rsl/peano/a peano0.rsl, 107
./src/rsl/peano/a peano1.rsl, 108
./src/rsl/peano/a th.rsl, 136
./src/rsl/peano/c peano1.rsl, 112
./src/rsl/reverse.rsl , 106
./src/rsl/tests.rsl, 98
./src/rsl/theory/a0.rsl , 133
./src/rsl/theory/a1.rsl , 133
./src/rsl/theory/a th.rsl , 133
./src/rsl/theory/b0.rsl , 134
./src/rsl/theory/b1.rsl , 134
./src/rsl/theory/b th.rsl , 134
./src/rsl/theory/c0.rsl , 135
./src/rsl/theory/c1.rsl , 135
./src/rsl/theory/c th.rsl , 135
./src/rsl/types.rsl, 97
./src/rsl/vals.rsl, 96
./src/rsl/vars.rsl, 94
./src/test/classman.zbx, 322
./src/test/classman.zsl, 319
./tmain.tex, 155
.zbx, 235
.zed, 234
.zsl, 235, 272
Книга Дней Рождений, 232
Логика высказываний, 249
абстрактный аппликативный стиль,
69
абстрактный стиль спецификации, 14
абстрактный тип данных, 67, 68
agp1.fmsd 1.02.10
аксиоматическое описание функции, 274
антиограничение множества значений, 271
антиограничение области определения, 271
аппликативный стиль, 116
аппликативный стиль спецификации, 15
атрибут стрелки arrowhead, 27
атрибут стрелки dir, 27
атрибут стрелки style, 27
атрибут узла shape, 26
атрибут dir, 32
базовый тип, 254, 277
белый ящик, 137
блок - схема, 18
буквальное воспроизведение, 55,
76
булиан , 264
черный ящик, 108, 137
четыре вида окон, 138
данное множество, 254
дефект, 167
дымовое тестирование, 108, 137
диаграмма состояний, 28, 138
домен абстрактного типа, 68
дополнение, 257
достаточная полнота спецификации , 88, 89
драйвер теста, 63
единица компиляции, 62
эффективность, 77
форма, 161
форма Бэкуса - Наура, 36
170
функции - запросы, 86
функции перехода, 86
функции состояния, 86
функции выхода, 86
функция ’предыдущее число’, 275
функция ’следующее число’, 275
группа языка RAISE, 86
императивный стиль , 116
императивный стиль спецификации, 15
имя схемы, 238
индексирование списка, 98
инвариант, 120, 167
иррефлексивно – транзитивное
замыкание, 272
канал данных, 161
кластер, 25
компилятор CHM файлов, 45
композиционный анализ, 83
компрессированный HTML, 138
компрессированный html, 45
конкретная императивная спецификация, 107
конструктор, 278
конструкторы, 86
контракт, 69
корректность , 77
линейка масштабирующих объектов , 161
логика утверждений, 249
математическая библиотека, 270
математический режим, 71
множество значений , 266
модуль, 62, 78
мониторинг, 167
agp1.fmsd 1.02.10
мощность, 276
не определяемый тип, 68, 97
неисправность, 167
неопределяемый тип, 22
неустойчивая последовательность
Мюллера, 98
объединение множеств, 256
область определения, 266
обратное отношение, 267, 272
образ множества при заданном
отношении, 271
ограничение целостности, 289
ограничение множества значений, 271
ограничение области определения, 271
окно данных, 161, 163
окно визуализации множества,
163
операционная система, 161
оператор обновления, 286
ошибка, 167
отказ, 167
панель, 161
переименование, 300
переменные состояния, 292
пересечение множеств, 256
подграф, 25
подключением схемы, 296
поле, 161
последовательная композиция, 301
постусловие, 70
повторное использование, 77
преамбула, 52
предметный указатель, 55, 139
171
предусловие, 69
приложение, 161
применение отображения, 98
принцип самодокументирования,
12
пробел, 72
процесс, 160
проектирование схемы, 300
пространство состояний приложения, 291
прототипирование, 16
прямая композиция отношений,
270
рамочный стиль, 235
распределенная форма операций,
286
расширяемость, 77
раздел предикатов, 239
разделенный, 287
разность множеств, 256
рефлексивно – транзитивное замыкание, 272
схема, 238, 289
схема операций, 293
символ тильда, 72
следующее состояние, 293, 300
сокращенное определение множества, 257
сорт, 97
состояние ПЕРЕД, 293
состояние ПОСЛЕ, 293, 300
совместимость, 77
спецификация, 14
стек, 67
степень множества, 264
agp1.fmsd 1.02.10
172
степень отношения, 272
стиль LaTex-а , 234
стрелка, 25
свободный тип, 278
свободный тип (англ. free type,
аналог перечисления), 310
шаблон параметра, 269
шаблон?, 284
текстовый стиль, 235, 239, 305
текстовый стиль спецификации,
272
текущее состояние, 293
тестовый вариант, 98, 108, 137
тип интереса, 68, 125
точка наивысшей абстракции входного потока, 84
требования , 65
условия уверенности, 129
устойчивость, 77
утилита проверки правописания,
290
уточнение данных, 279
узел, 25
выключенная формула, 72
выражение let, 247
вполне упорядоченность, 288
явное перечисление, 278
Doxygen , 37
book, 53
box style, 284
boxedminipage.sty , 93
amsmath, 73
application, 161
article, 53
edge, 25
efficiency, 77
error, 167
extendibility, 77
extreport, 53
backward relational composition,
271
basic type, 254, 277
cardinality, 276
CHM, 45
CHM файл, 45
circo.exe, 24
cluster, 25
compatibility, 77
complementation, 257
confidence condition, 129
constraint, 289
constructor, 278
correctness, 77
data refinement, 279
data type, 278
defect, 167
difference, 256
disjoint, 287
disjointness , 286
distributed operations , 286
domain, 266
domain anti-restriction, 271
domain restriction, 271
dot.exe, 24
dotty.exe, 24
dyadic, 286
fault, 167
agp1.fmsd 1.02.10
filed, 161
fixedsize, 224
flowchart, 18
forward relational composition, 270
free type, 278, 310
generic construction, 284
generic parameters, 269
given set, 254, 277
grammar checker, 13, 232, 290
GraphViz, 140
Graphviz, 37
gvedit.exe, 24
height, 224
hhc.exe, 45
hyperref, 238
index.hhp , 45
input, 239
intersection, 256
invariant, 167
inverse relation, 267, 272
irreflexive – transitive closure, 272
label, 25
lslr., 39
makeindex.exe , 56
maplet, 167
maplet notaion, 266
matematical toolkit, 270
math0.zbx, 233
math1.zbx, 233
math1.zbx , 245
math2.zbx, 290
mathX.zbx , 233
173
Microsoft HTML Help Workshop,
45
node, 25
operation schema, 293
operational system, 161
overriding operator, 286
oz.sty, 233
panel, 161
partitioning, 286
power set, 264
predicate Logic, 249
predicate logic, 249
RAISE Development Method, 88
range, 266
range anti-restriction, 271
range restriction, 271
record window, 161
records window, 163
reflexive – transitive closure, 272
relational image, 271
relational iteration, 272
report, 53
requirement, 65
reusability, 77
RLG , 86
robustness, 77
RSL, 159
rslenv.sty , 93
RSLTC, 129
schema, 289
schema hiding, 300
schema inclusion, 296
agp1.fmsd 1.02.10
schema piping, 302
schema projection, 300
schema renaming, 300
sequential composition , 301
set comprehension, 257
short record, 97
state machine, 28
state space, 291
state variables, 292
STS- декомпозиция, 84
subgraph, 25
title.tex , 54
total order, 288
UML, 16
union, 97, 256
variant, 97
verbatiminput, 239
width, 224
zedcompatible, 238
ZLIBPATH, 233
ZSL plain text style, 235
ztc.exe, 318
ztc.exe , 232
ztc.hlp , 234
ztc.sty, 233
174
agp1.fmsd 1.02.10
175
Список литературы
[1] EBNF Visualizer [Електронний ресурс] – Режим доступу до ресурсу: http://dotnet.jku.at/applications/visualizer/.
[2] Haxthausen A.E. Lecture Notes on The RAISE Development
Method, 1999. http://www2.imm.dtu.dk/courses/02263/E20/
Files/methodnotes99.pdf.
[3] ATT and Lucent Bell Labs. Graphviz - graph visualization software.
http://www.graphviz.org/.
[4] Meyer B. Object - oriented Software Construction. 2-nd edition.
Santa Barbara :ISE Inc, USA, p. 1284, 2000.
[5] George C.
Introduction to RAISE, 2002.
http://www.
sel.unsl.edu.ar/ApuntesMaes/Anteriores/RAISE/Apunte_
ChrisGeorge/report249.pdf.
[6] George C. RAISE Tool User Guide, 2008. https://raisetools.
github.io/material/documentation/ug.pdf.
[7] Morgan C.
Laws of the Logical Calculi / C.C.Morgan ,
J.W.Sanders //. Technical Monograph RPG-78, Oxford University
Computing Laboratory, Wolfson Building, Parks Road, Oxford,
UK, September 1989.
https://www.google.ru/url?sa=t&
rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=
2ahUKEwjkjaGEnKf1AhUqsaQKHeIyDwkQFnoECAIQAQ&url=https%
3A%2F%2Fwww.cs.ox.ac.uk%2Fpublications%2Fbooks%2FPfS%
2FPfS-R.ps.gz&usg=AOvVaw27SjUZZnUetPtM16pnTy7n.
[8] Heesch D. Doxygen - documentation system. http://www.stack.
nl/~dimitri/doxygen/index.html.
[9] Parnas D.L. Really rethinking ’formal methods’. Computer (IEEE
Computer Society), 43:28–34, 01 2010.
agp1.fmsd 1.02.10
176
[10] Erik van Veenendaal and Glossary Working Party. . Стандартный
глоссарий терминов, используемых в тестировании программного обеспечения. ver.2, 2008. - 55 p.
[11] Grant A., Owens M. Неполное Руководство по SQLite для
пользователей Windows / А.Г.Пискунов (пер. с англ.), 8
2019. Интернет ресурс: https://drive.google.com/file/d/
10XPFuUPYgzxuO5cwhdnqsse3p1QqO-vs/view?usp=sharing.
[12] The RAISE Language Group. The RAISE Specification Language,
1992. CRI A/S, Denmark, 417 pages, https://raisetools.
github.io/material/documentation/raise-language.pdf.
[13] Haxthausen A.E. Алгебраическое проектирование класса /
А.Г.Пискунов (пер. с англ.)//, 2010. Интернет ресурс: https:
//www.researchgate.net/publication/334173954.
[14] ISO/IEC 2382:2015. Информационные технологии СЛОВАРЬ. –
Москва, Стандартинформ, 2016 – 208 с.
[15] Bowen J. Formal Specification and Documentation using Z: A Case
Study Approach. Itp - Media, 06 2003.
[16] Hoffmann J. The listings package / J.Hoffmann, B.Moses, H.Carsten
, 2024. Интернет ресурс: https://ctan.math.illinois.edu/
macros/latex/contrib/listings/listings-devel.pdf.
[17] Jacky J. The Way of Z: Practical Programming with formal
Methods. Cambridge University Press, USA, New York, 1997. ISBN
0-521-55041-6.
[18] Wordsworth J.B. Software Development with Z. A Practical
Approach to Formal Methods in Software Engineering. AddisonWesley, 1992. ISBN 0-201-62757-4.
[19] X. Jia. ZTC: A Type Checker for Z Notation. User’s Guide.
DePaul University, USA, 1998. Version 2.03, Division of Software
agp1.fmsd 1.02.10
177
Engineering, School of Computer Science, Telecommunication, and
Information Systems.
[20] Spivey J.M. The Z Notation: A Reference Manual, 2nd edition.
Prentice Hall International Series in Computer Science, 1992.
[21] McMahon L.E. Sed: A non-interactive text editor. http://sed.
sourceforge.net/#docs.
[22] Martin R.C. The Liskov Substitution Principle, 2003. C++ Report,
March 1996, https://objectmentor.com/resources/articles/
lsp.pdf.
[23] Myers G.J. Reliable Softwart Throught Composite Design. (New
York: Petrocelli, 1975).
[24] Pikovsky Nikolaev M.V., Medinetz A.Y. Rio - plan text formater.
Интернет ресурс: http://agp1.adr.com.ua/rio.html.
[25] Piskunov A.G. Inheritance of Abstract Automata /. Вестник Киевского ун-та. Серия: Кибернетика, 2011, Вып.11. - с. 40-44. Интернет ресурс: https://www.researchgate.net/publication/
348234288.
[26] Piskunov A.G. RIO to LaTex convertor / А.Г.Пискунов // . Интернет ресурс: http://agp1.adr.com.ua/mkTex.html.
[27] Piskunov A.G. SQLite как хранилище пространственных данных / А.Г.Пискунов // Тезисы докладов 12-й международной
конференции «Теоретические и прикладные аспекты построения программных систем». – К. КНУ, 2015. Интернет ресурс:
https://www.researchgate.net/publication/348558938.
[28] Piskunov A.G. Использование TCL/TK: база данных для
хранения курсов валют c нуля. Пояснительная записка /
А.Г.Пискунов //, 2009.
Интернет ресурс: https://www.
researchgate.net/publication/368660786.
agp1.fmsd 1.02.10
178
[29] Piskunov A.G. Пояснительная записка проекта Args - обработки аргументов командной строки / Пискунов А.Г., Гись Д.И.
//, 2018. Интернет ресурс: https://www.researchgate.net/
publication/344653273.
[30] Piskunov A.G. 2022. LaTex и требования государственного
стандарта [Електронний ресурс] / А.Г.Пискунов // К.: НАУ,
ФККПИ, каф. прикладная математика. – 2022. – Режим доступа к ресурсу: https://www.researchgate.net/publication/
359860334.
[31] Piskunov A.G. Классы, функции и проектирование приложений / А.Г.Пискунов //, 2022. Интернет ресурс: https://www.
researchgate.net/publication/363644087.
[32] The RAISE Language Group. The RAISE SPECIFICATION
LANGUAGE.
UNU/IIST, Prentice Hall Europe, Denmark,
1992, 1992.
https://raisetools.github.io/material/
documentation/raise-language.pdf.
[33] The RAISE Language Group.
The RAISE Development
Method, 1999.
https://raisetools.github.io/material/
documentation/raise-method.pdf.
[34] Пискунов А.Г.
Наследование абстрактных автоматов /
А.Г.Пискунов //, 2007.
Интернет ресурс: https://www.
researchgate.net/publication/349098038.
[35] Пискунов А.Г. Конспект лекций. Компиляторы С++ и разработка консольных приложений (Часть 1)/ А.Г.Пискунов //.
12 2020. Интернет ресурс: https://www.researchgate.net/
publication/344141630.
[36] Пискунов А.Г. Примеры схем языка z для утилиты ztc /
А.Г.Пискунов //, 2023, 54 с. Интернет ресурс: https://www.
researchgate.net/publication/370048200_woz01201pdf.
agp1.fmsd 1.02.10
179
[37] Пискунов А.Г. .NET и ZTC: документирование функций без
циклов / А.Г.Пискунов, А.Г.Сиренко, М.Д.Тетёрко // , 2024. Интернет ресурс: https://www.researchgate.net/publication/
378139007.
[38] Пискунов А.Г. Алгебраическое проектирование и тестирование
ПО / А.Г.Пискунов, Н.П.Тупко, И.А.Петренко //, 2024. Интернет ресурс: https://www.researchgate.net/publication/
377625032.
[39] Пискунов А.Г. Конвертор схем языка RSL в текст для LaTex,
2024.
/ А.Г.Пискунов // Интернет ресурс: https://www.
researchgate.net/publication/379638905.
[40] Пискунов А.Г. Формальное тестирование функций вещественного аргумента / А.Г.Пискунов, Н.П.Тупко, Н.В.Топиха //
, 2024. Интернет ресурс: https://www.researchgate.net/
publication/380694143.
[41] Пискунов А.Г. Условия алгебраического тестирования функций со свойствами метрики / А.Г.Пискунов // , 2025. Интернет ресурс: https://www.researchgate.net/publication/
390491926.
[42] Александрян Р.А. Общая топология. Учебное пособие для вузов /Р.А. Александрян, Э.А. Мирзаханян//. М: Высшая школа,
1979.
[43] Сюткин В. Набор математических формул в LaTex, 2002. 46
c., Интернет ресурс: https://grammarware.net/text/syutkin/
MathInLaTeX.pdf.
[44] Кулямин В.В. Стандартизация и тестирование реализаций математических функций, работающих с числами с плавающей
точкой. page 32, 2007. //Труды ИСП РАН, https://www.
researchgate.net/publication/229042158.
agp1.fmsd 1.02.10
180
[45] Васильев В.С.
Блок-схемы алгоритмов. ГОСТ. Примеры.
https://pro-prof.com/archives/1462.
[46] Буч Г. Объектно-ориентированный анализ и проектирование
с примерами приложений на С++. 2-е изд. М.:Издательство
Бином; СПб.:Невский диалект, 1999.
[47] Буч Г. Язык UML. Руководство пользователя. 2-е изд.:/ Г.Буч,
Д.Рамбо, И.Якобсон. М.: ДМК Пресс, 2006, 2006.
[48] Майерс Г. Надежность программного обеспечения / Пер. с англ.
Ю.Ю.Галимов под ред. В.Ш.Кауфмана. М.: Мир, 1980.
[49] Майерс Г. Искусство тестирования программ/ Пер. с англ. под
ред. Б.А.Позина. М.: Финансы и статистика, 1982.
[50] Парнас Д.Л. Реальное переосмысление ’формальных методов’
/ пер.с англ. В.В.Кулямин//, 2010. http://citforum.ru/SE/
quality/fm_rethinking/.
[51] ДСТУ 3008:2015. ЗВIТИ У СФЕРI НАУКИ I ТЕХНIКИ. Структура та правила оформлювання / уклали: В. Земцева; Ю. Полiщук, Р. Санченко, Л. Шрамко; А. Ямчук. – Київ, ДП УкрНДНЦ,
2016. – 26 с.
[52] Дейт К.Дж. . Введение в системы баз данных = An Introduction
to Database System, 7th Edition. . — М.: Вильямс, 2001. — С.
1072. — ISBN 5-8459-0138-3.
[53] Жук П.Ф. Математична логiка та теорiя алгоритмiв. Практикум. / уклад.: Жук П.Ф., Супрун О.М.//. 2015. К.: Вид-во Нац.
авiац. ун-ту ’НАУ-друк’, 2015, - 52 с.
[54] Арнольд И.В. Задачи для детей от 5 до 15 лет. – 2-е изд., дополненное. МЦНМО, 2007.
[55] Кафедра системного программирования МГУ. Методы Формальной Спецификации Программ.
http://www.ispras.
agp1.fmsd 1.02.10
181
ru/~RedVerst/RedVerst/Lecturesandtrainingcourses/
MSUcourseFormalspecificationofsoftware/RMain.html.
[56] Кузьменкова Е.А. Практикум по формальной спецификации
программ на языке RSL. / Е.А. Кузьменкова, А.К. Петренко
// М.: Издательский отдел факультета ВМК МГУ, 2008. http:
//sp.cs.msu.ru/courses/fmsp/meth2008.pdf.
[57] Омельчук Л.Л.
Формальнi методи специфiкацiї програм.
Київський нацiональний унiверситет iменi Тараса Шевченка,
факультет кiбернетики, Київ, 2010. Навчальний посiбник. Затверджено вченою радою факультету кiбернетики 21.12.2009.
[58] Майерс Г.
Композиционное проектирование приложения , 2009.
Интернет ресурс: https://docplayer.ru/
48434435-G-mayers-kompozicionnoe-proektirovanie-prilozheniya.
html.
[59] Манин Ю.И.
Вычислимое и невычислимое.
Советское радио, 1980. https://obuchalka.org/2012030563851/
vichislimoe-i-nevichislimoe-manin-u-i-1980.html.
[60] Мейер Б. Основы объектно-ориентированного программирования. 2-е издание. М.:Национальный Открытый Университет
ИНТУИТ, 2016.
[61] Мейерс С. Эффективный и современный С++: 42 рекомендации по исполыованию С++11 и С++14. Пер. с англ. - М. : ООО
"ИЛ. Вильяме 2016. - 304 с.
[62] Нечаев В.И. Числовые системы. Пособие для студентов пед. интов., М., «Просвещение», 1975 - 199 с. Интернет ресурс: http:
//scask.ru/q_book_ds.php?id=35.
[63] Пiскунов О.Г. Розробка консольних i вiконних додаткiв на мовi
C# / О.Г.Пiскунов // , 2020. Интернет ресурс: https://www.
researchgate.net/publication/374847788.
agp1.fmsd 1.02.10
182
[64] Пiскунов О.Г. Розробка додаткiв засобами мови програмування
C# / О.Г.Пiскунов, E.V.Ivohin, M.M.Makhno //. К.: Видавничополiграфiчний центр ’Київський унiверситет’, 09 2021. Интернет ресурс: https://www.researchgate.net/publication/
354860614.
[65] Пiскунов О.Г. АЛГОРИТМIЧНI МОВИ ТА ПРОГРАМУВАННЯ. Лабораторний практикум / А.Г.Пискунов, О.П.Томащук,
O.V.Gavrilenko //. К.: НАУ, 2022. Интернет ресурс: https:
//www.researchgate.net/publication/363044064.
[66] Пiскунов О.Г. Розробка клiєнт - серверних додаткiв мовою C#
та SQLite / О.Г.Пiскунов, Л.В.Єсик, О.П.Томащук //, 2022. Интернет ресурс: https://www.researchgate.net/publication/
365126475.
[67] О.Г. ПIСКУНОВ, Н.П. ТУПКО, and I.А. ПЕТРЕНКО. Алгебраїчне проєктування програмного забезпечення. Iнформацйнi
технологiї та суспiльство, (5 (11)):50–59, 01 2024.
[68] Пискунов А.Г.
Использование языков формальных спецификаций при проектировании реляционных баз данных.
/ А.Г.Пискунов, В.Л.Илюхин // sql.ru - 2003, 13 с., Интернет ресурс: https://www.researchgate.net/publication/
358661467.
[69] Пискунов А.Г. Doxygen и Graphviz: ДОКУМЕНТИРОВАНИЕ
ПРОЕКТОВ НА C# / А.Г.Пискунов, А.С.Горбань //. Журн.
Алгоритм, 4(10):16, 05 2006. Интернет ресурс: https://www.
researchgate.net/publication/346447041.
[70] Пискунов А.Г. Graphviz и Sed: построение схем иерархии наследования / А.Г.Пискунов, С.М.Петренко //. Журн. Алгоритм,
3(9):15, 03 2006. Интернет ресурс: https://www.researchgate.
net/publication/348917724.
agp1.fmsd 1.02.10
183
[71] Пискунов А.Г.
Cистема синхронизации каталогов ’HTTP
Backup’/ А.Г.Пискунов //, 2009.
[72] Пискунов А.Г. Проектирование и декомпозиция двунаправленных потоков данных интерактивных систем (Часть 1) /
А.Г.Пискунов //, 2009. Интернет ресурс: https://er.nau.edu.
ua/bitstream/NAU/39629/1/dataFlow.pdf.
[73] Пискунов А.Г.
Проектирование и декомпозиция двунаправленных
потоков
данных
интерактивных
систем (Часть 2) / А.Г.Пискунов //, 2009.
Интернет
ресурс:
https://drive.google.com/file/d/1kHcdRW_
9WkqJATAR3KlAjp6lVCa1D-qa/view?usp=sharing.
[74] Пискунов А.Г. Об отличиях между понятиями типа и класса
/ А.Г.Пискунов //. Вестник Киевского университета. Компьютерные науки., 3,:стр.106–114, 2015. Интернет ресурс: https:
//www.researchgate.net/publication/344177979.
[75] Пискунов А.Г. Лабораторный практикум. Компиляторы С++ и
разработка консольных приложений (Часть 1)/ А.Г.Пискунов//
, 2018. Интернет ресурс: https://www.researchgate.net/
publication/344218310.
[76] Пискунов А.Г. Разработка консольных и оконных приложений
на языке C# / А.Г.Пискунов // , 2019. Интернет ресурс: https:
//www.researchgate.net/publication/344154563.
[77] Пискунов А.Г. SQLite и введение в разработку клиент - серверных приложений на языке C# / А.Г.Пискунов //, 2020. Интернет ресурс: https://www.researchgate.net/publication/
344750300.
[78] Пискунов А.Г.
Конспект лекций. Разработка консольных
приложений c элементами С++ (Часть 2)/ А.Г.Пискунов,
И.А.Петренко // . 05 2020. Интернет ресурс: https://www.
researchgate.net/publication/341345204.
agp1.fmsd 1.02.10
184
[79] Пискунов А.Г. Разработка консольных приложений с элементами С++ (Часть 2)/ А.Г.Пискунов //, 05- 2020. Интернет ресурс:
https://www.researchgate.net/publication/344141588.
[80] Пискунов А.Г. Документирование процесса разработки ПО
/ А.Г.Пискунов //, 2021. Интернет ресурс: https://www.
researchgate.net/publication/367463805.
[81] Пискунов А.Г. Арифметика Пеано: от спецификации к классу / А.Г.Пискунов, В.И.Рудык, И.А.Петренко //, 12 2022. Интернет ресурс: https://www.researchgate.net/publication/
365979331.
[82] Пискунов А.Г. NUnit и некоторые вопросы модульного тестирования / А.Г.Пискунов // , 2023. Интернет ресурс: https:
//www.researchgate.net/publication/374422606.
[83] Пискунов А.Г. Переопределение сложения: небезопасное наследование в группе целых / А.Г.Пискунов, А.М.Мичуда //,
01 2023. Интернет ресурс: https://www.researchgate.net/
publication/366867037.
[84] Львовский С.М. Набор и вёрстка в системе LaTeX, 5-е издание,
переработанное. МЦНМО, 2014.
[85] С.Макконелл. СОВЕРШЕННЫЙ КОД. Практическое руководство по разработке ПО. Второе издание /. MS Press, Пер.с англ.
— М.: Издательство «Русская редакция»„ 2010.
[86] Куликов С.С.
Тестирование программного обеспечения. Базовый курс. 2-е издание.
Минск: Издательство ’Четыре четверти’, 2017.
ISBN: 978-985-581-362-1,
https://careers.epam.by/content/dam/epam/by/book_epam_
by/Software_Testing_Basics_2_izdanie.pdf.
[87] Куликов С.С. Тестирование программного обеспечения. Базовый курс. 3-е издание. EPAM Systems, 2021. version: 3.0.8.
agp1.fmsd 1.02.10
185
[88] Степанов А.А. От математики к обобщенному программированию / А.А.Степанов, Д.Э.Роуз // пер. с англ. А.А.Слинкина.
М.: ДМК Пресс, 2015.
agp1.fmsd 1.02.10
A
186
Исходные тексты проект Hello
Для генерации документов использовался следующий пример - проект на C-е, состоящий из двух файлов
• main.cs;
• lib.cs;
main.cs file:
---- File:./src/csharp/main.cs
using System;
using System.IO;
namespace adm_w{
public class gVars
/// Глобальные переменные приложения 1
/**
Эти переменные могут использоваться в каждом классе или каждой функции
приложения.
*/
{
public const string version = "0.92.1";
public const string
name = "DBManager";
public const string
path = "./var";
///< каталог временных файлов.
public const string
nm
= "adm_w.log";
public static string uuser
= "";
public static string upwd
= "";
}
class app {
static bool isArgs(string s){
bool r = false;
switch (s[0]) {
case ’-’: r = true; break;
case ’/’: r = true; break;
}
return r;
}
static bool isArgs(string arg, params string[] vals) {
bool r = false;
for (int i = 0; i < vals.Length; i++){
if (arg.Substring(1).ToLower() == vals[i]) {
r = true;
agp1.fmsd 1.02.10
187
break;
}
}
return r;
}
static void Main(string[] args) {
for (int i = 0; i < args.Length; i++){
if (isArgs(args[i])) {
if (isArgs (args[i], "?","h","help"))
goto
error;
else if (isArgs (args[i], "u")) {
i++;
if (i >= args.Length ) goto error;
gVars.uuser= args[i];
}
else if (isArgs (args[i], "p")) {
i++;
if (i >= args.Length ) goto error;
gVars.upwd= args[i];
}
}
}
c.wrLn ("Hello, world2!"); b.wrLn ("Hello, world!");
return;
error:
string msg = "where:\n"+ "\t -u unisay user\n" + "\t -p unisay pwd\n";
a.wrLn ("usage "+ gVars.name +": mnr [-u xx -p yy ]" ); b.wrLn (msg );
}
}}
---- End Of File:./src/csharp/main.cs
lib.cs file:
---- File:./src/csharp/lib.cs
/** \file
\brief файл с библиотекой
*/
using System;
using System.IO;
namespace adm_w{
class a{
static public void
wrLn (
Console.WriteLine (s);
}
string s
) {
/// \callgraph
agp1.fmsd 1.02.10
188
}
class b: a {
int dummy; }
class c: b {
int dummy2; }
class d
{
int dummy; }
class e
{
public int dummy;
public d
foo;
public void x (string s) { a.wrLn(s); }
}
}
---- End Of File:./src/csharp/lib.cs
B
Файл настройки Doxygen-а для проекта Hello
---- File:./src/csharp/hello.
# Doxyfile 1.4.6-NO
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
#
TAG = value [value, ...]
# For lists items can also be appended using:
#
TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#--------------------------------------------------------------------------# Project related configuration options
#--------------------------------------------------------------------------# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME
=
hello
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER
=
agp1.fmsd 1.02.10
189
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY
= _bld
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
# format and will distribute the generated files over these directories.
# Enabling this option can be useful when feeding doxygen a huge amount of
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS
= NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
# Swedish, and Ukrainian.
OUTPUT_LANGUAGE
= Russian
# This tag can be used to specify the encoding used in the generated output.
# The encoding is not always determined by the language that is chosen,
# but also whether or not the output is meant for Windows or non-Windows users.
# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
# forces the Windows encoding (this is the default for the Windows binary),
# whereas setting the tag to NO uses a Unix-style encoding (the default for
# all platforms other than Windows).
USE_WINDOWS_ENCODING
= YES
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC
= YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
agp1.fmsd 1.02.10
190
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF
= YES
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
# in this list, if found as the leading text of the brief description, will be
# stripped from the text and the result after processing the whole list, is
# used as the annotated text. Otherwise, the brief description is used as-is.
# If left blank, the following values are used ("$name" is automatically
# replaced with the name of the entity): "The $name class" "The $name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
ABBREVIATE_BRIEF
=
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC
= NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB
= NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES
= NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH
=
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells
# the reader which header file to include in order to use a class.
# If left blank only the name of the header file containing the class
agp1.fmsd 1.02.10
191
# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
STRIP_FROM_INC_PATH
=
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful is your file systems
# doesn’t support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES
= NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explicit @brief command for a brief description.
JAVADOC_AUTOBRIEF
= NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
# If the DETAILS_AT_TOP tag is set to YES then Doxygen
# will output the detailed description near the top, like JavaDoc.
# If set to NO, the detailed description appears after the member
# documentation.
DETAILS_AT_TOP
= NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS
= YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES
= NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
agp1.fmsd 1.02.10
TAB_SIZE
192
= 8
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n’s in the value part of an alias to insert newlines.
ALIASES
=
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C
= NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
# sources only. Doxygen will then generate output that is more tailored for Java.
# For instance, namespaces will be presented as packages, qualified scopes
# will look different, etc.
OPTIMIZE_OUTPUT_JAVA
= NO
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
# include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT
= NO
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC
= NO
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING
= YES
agp1.fmsd 1.02.10
193
#--------------------------------------------------------------------------# Build related configuration options
#--------------------------------------------------------------------------# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL
= YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE
= NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC
= YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES
= YES
# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS
= NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS
= NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES
= NO
agp1.fmsd 1.02.10
194
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS
= NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
# documentation blocks found inside the body of a function.
# If set to NO (the default) these blocks will be appended to the
# function’s detailed documentation block.
HIDE_IN_BODY_DOCS
= NO
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS
= NO
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES
= NO
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES
= NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES
= YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO
= YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
agp1.fmsd 1.02.10
195
# declaration order.
SORT_MEMBER_DOCS
= YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS
= NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME
= NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST
= YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST
= YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST
= YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS
=
agp1.fmsd 1.02.10
196
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or define consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES
= 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES
= YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is NO.
SHOW_DIRECTORIES
= NO
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from the
# version control system). Doxygen will invoke the program by executing (via
# popen()) the command <command> <input-file>, where <command> is the value of
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
FILE_VERSION_FILTER
=
#--------------------------------------------------------------------------# configuration options related to warning and progress messages
#--------------------------------------------------------------------------# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET
= NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS
= YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
agp1.fmsd 1.02.10
197
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED
= YES
# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some
# parameters in a documented function, or documenting parameters that
# don’t exist or using markup commands wrongly.
WARN_IF_DOC_ERROR
= YES
# This WARN_NO_PARAMDOC option can be abled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC
= NO
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text. Optionally the format may contain
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT
= "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE
=
#--------------------------------------------------------------------------# configuration options related to the input files
#--------------------------------------------------------------------------# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT
=
./csharp/
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
agp1.fmsd 1.02.10
198
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
FILE_PATTERNS
=
main.txt *.cs
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE
= NO
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE
=
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
EXCLUDE_SYMLINKS
= NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories. Note that the wildcards are matched
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
EXCLUDE_PATTERNS
=
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH
=
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS
=
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
agp1.fmsd 1.02.10
EXAMPLE_RECURSIVE
199
= NO
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH
=
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER
=
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
FILTER_PATTERNS
=
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES
= NO
#--------------------------------------------------------------------------# configuration options related to source browsing
#--------------------------------------------------------------------------# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER
= NO
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES
= NO
agp1.fmsd 1.02.10
200
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS
= YES
# If the REFERENCED_BY_RELATION tag is set to YES (the default)
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES (the default)
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION
= YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU’s global source
# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS
= NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS
= YES
#--------------------------------------------------------------------------# configuration options related to the alphabetical class index
#--------------------------------------------------------------------------# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX
= NO
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX
= 5
agp1.fmsd 1.02.10
201
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX
=
#--------------------------------------------------------------------------# configuration options related to the HTML output
#--------------------------------------------------------------------------# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML
= YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank ‘html’ will be used as the default path.
HTML_OUTPUT
= html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION
= .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER
=
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER
=
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet. Note that doxygen will try to copy
# the style sheet file to the HTML output directory, so don’t put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET
=
agp1.fmsd 1.02.10
202
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS
= YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP
= NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
# written to the html output directory.
CHM_FILE
=
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
HHC_LOCATION
=
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI
= NO
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC
= NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND
= NO
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX
= NO
agp1.fmsd 1.02.10
203
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE
= 4
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature.
GENERATE_TREEVIEW
= NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH
= 250
#--------------------------------------------------------------------------# configuration options related to the LaTeX output
#--------------------------------------------------------------------------# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX
= YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank ‘latex’ will be used as the default path.
LATEX_OUTPUT
= latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank ‘latex’ will be used as the default command name.
LATEX_CMD_NAME
= latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank ‘makeindex’ will be used as the
# default command name.
MAKEINDEX_CMD_NAME
= makeindex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
agp1.fmsd 1.02.10
204
# save some trees in general.
COMPACT_LATEX
= NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE
= a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES
=
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER
=
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS
= NO
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX
= NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE
= NO
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES
= NO
#---------------------------------------------------------------------------
agp1.fmsd 1.02.10
205
# configuration options related to the RTF output
#--------------------------------------------------------------------------# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF
= NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank ‘rtf’ will be used as the default path.
RTF_OUTPUT
= rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF
= NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS
= NO
# Load stylesheet definitions from file. Syntax is similar to doxygen’s
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE
=
# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen’s config file.
RTF_EXTENSIONS_FILE
=
#--------------------------------------------------------------------------# configuration options related to the man page output
#--------------------------------------------------------------------------# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN
= NO
agp1.fmsd 1.02.10
206
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank ‘man’ will be used as the default path.
MAN_OUTPUT
= man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine’s section .3)
MAN_EXTENSION
= .3
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS
= NO
#--------------------------------------------------------------------------# configuration options related to the XML output
#--------------------------------------------------------------------------# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML
= NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank ‘xml’ will be used as the default path.
XML_OUTPUT
= xml
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_SCHEMA
=
# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_DTD
=
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
agp1.fmsd 1.02.10
207
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING
= YES
#--------------------------------------------------------------------------# configuration options for the AutoGen Definitions output
#--------------------------------------------------------------------------# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF
= NO
#--------------------------------------------------------------------------# configuration options related to the Perl module output
#--------------------------------------------------------------------------# If the GENERATE_PERLMOD tag is set to YES Doxygen will
# generate a Perl module file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD
= NO
# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX
= NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader. This is useful
# if you want to understand what is going on. On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY
= YES
# The names of the make variables in the generated doxyrules.make file
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
# This is useful so different doxyrules.make files included by the same
# Makefile don’t overwrite each other’s variables.
agp1.fmsd 1.02.10
208
PERLMOD_MAKEVAR_PREFIX =
#--------------------------------------------------------------------------# Configuration options related to the preprocessor
#--------------------------------------------------------------------------# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING
= YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION
= NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF
= NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES
= YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH
=
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS
=
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
agp1.fmsd 1.02.10
209
# instead of the = operator.
PREDEFINED
=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED
=
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen’s preprocessor will remove all function-like macros that are alone
# on a line, have an all uppercase name, and do not end with a semicolon. Such
# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS
= YES
#--------------------------------------------------------------------------# Configuration::additions related to external references
#--------------------------------------------------------------------------# The TAGFILES option can be used to specify one or more tagfiles.
# Optionally an initial location of the external documentation
# can be added for each tagfile. The format of a tag file without
# this location is as follows:
#
TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
#
TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths or
# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
TAGFILES
=
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE
=
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
agp1.fmsd 1.02.10
ALLEXTERNALS
210
= YES
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
# in the modules index. If set to NO, only the current project’s groups will
# be listed.
EXTERNAL_GROUPS
= YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of ‘which perl’).
PERL_PATH
= /usr/bin/perl
#--------------------------------------------------------------------------# Configuration options related to the dot tool
#--------------------------------------------------------------------------# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
# this option is superseded by the HAVE_DOT option below. This is only a
# fallback. It is recommended to install and use dot, since it yields more
# powerful graphs.
CLASS_DIAGRAMS
= YES
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS
= YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT
= YES
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH
= YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
agp1.fmsd 1.02.10
211
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH
= YES
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS
= YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG’s Unified Modeling
# Language.
UML_LOOK
= NO
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS
= YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH
= YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH
= YES
# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
# generate a call dependency graph for every global function or class method.
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command.
CALL_GRAPH
= YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY
= YES
# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
agp1.fmsd 1.02.10
212
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH
= YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT
= png
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH
=
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).
DOTFILE_DIRS
=
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_WIDTH
= 1024
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_HEIGHT
= 1024
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that a graph may be further truncated if the graph’s
# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
# the graph is not depth-constrained.
MAX_DOT_GRAPH_DEPTH
= 0
agp1.fmsd 1.02.10
213
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, which results in a white background.
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
DOT_TRANSPARENT
= NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS
= NO
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND
= YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP
= YES
#--------------------------------------------------------------------------# Configuration::additions related to the search engine
#--------------------------------------------------------------------------# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE
= NO
---- End Of File:./src/csharp/hello.
C
Пример файла пояснительной записки
Приложение содержит текстовый файл отчета проекта [29]:
---- File:./src/csharp/args.txt
agp1.fmsd 1.02.10
214
/**
\mainpage Пояснительная записка проекта Args
\date 2014-2017
\section Введение
Пояснительная записка к проекту args - библиотеки ввода и разбора параметров приложения
и выдачи подсказки - страницы использования приложения (usage).
Параметры приложения могут вводится как аргументы командной строки
либо как поля автоматически генерируемого диалогового окна.
Разработчики
А.Г.Пискунов, Д.И.Гись, О.С.Мисуна.
В пояснительной записке используются следующие термины:
аргумент командной строки элемент массива args из
‘static void Main(string[] args)‘;
ключ, это аргумент командной строки, начинающийся на символ ’-’ или ’/’.
Библиотека игнорирует регистр букв;
синоним ключа, далее - синоним. Библиотека игнорирует регистр букв;
описание ключа;
параметр ключа.
например,
на следующей странице использования приложения для тестирования библиотеки
----
to test command line arguments (ver:2.10.0)
usage:
a [-?] [-d] [-v] [-ln NNN] [-l LLL] [-p PPP] -f FLNM -t1 | -t2 | -t3
options:
-?
: to see this help: True
-d
: debug mode: False
-v
: additional info: True
-ln NNN
: log level names:{Spam Debug Warning Stats Error FatalError Info Ignore}: Err
-l LLL
: log level (1..8): 1
-p PPP
: percent for something (..100): 0.05
agp1.fmsd 1.02.10
215
-f FLNM
: data file: somefile.dat
-t1
: to do some work: False
-t2
: to do another work: False
-t3
: to show dialog window: False
’?’ means the same as ’help’
’d’ means the same as ’debug’
’v’ means the same as ’verbose’
’ln’ means the same as ’logName’
’l’ means the same as ’log’
’p’ means the same as ’percent’
’f’ means the same as ’file’
’t1’ means the same as ’workOne’
’t2’ means the same as ’workNext’
’t3’ means the same as ’window’
---ключами являются символы: -?, -v, -l.
синонимами:
help, verbose, log.
описаниями: ’to see this help’,
’additional info’, ’log level’.
параметрами ключа: LLL, PPP, FLNM.
Родительским классом для
разбора аргументов является
[Arg](@ref Args.Arg).
Страница подсказки выдается
в случае консольного приложения - в стандартный вывод ошибок,
в случае приложения Win32 - в диалоговое окно.
Свойство приложения, которое позволяет ему выдавать подсказку толи в стандартный
вывод ошибок, толи в диалоговое окно,
появилась в библиотеке благодаря помощи
участника форума
[sql.ru](http://www.sql.ru/forum/memberinfo.aspx?mid=152853)
При генерации диалогового окна для различных полей ввода можно задавать
признак того, что поле не надо редактировать.
признак того, что поля используется для ввода пароля и не надо отображать текст.
метод - делегат для проверки корректности введенного в поле значения.
В случае некорректного ввода, блокируются возможность вводить что либо в другие поля
agp1.fmsd 1.02.10
216
и нажимать кнопку Ок.
набор корректных альтернатив для ввода в поле.
Файл был создан утилитами
[Doxygen](http://doxygen.org)
и
[Microsoft’s HTML Help Workshop] (http://www.microsoft.com/en-us/download/details.aspx?id=21138).
С утилитой
[Doxygen](http://doxygen.org)
можно познакомится документе
[DOXYGEN И GRAPHVIZ : ДОКУМЕНТИРОВАНИЕ ПРОЕКТОВ НА C#](http://agp1.hx0.ru/dgIntro.html).
При создании текущей Пояснительной записки
использовались следующие параметры файла конфигурации утилиты
[Doxygen](http://doxygen.org):
DOXYFILE_ENCODING
= CP1251;
GENERATE_HTMLHELP
= YES.
Параметр для
создания CHM файла - файла подсказки из упакованного HTML.
В каталог, где строится документация
выводится файл index.hhp, который потом используется
утилитой hhc.exe
из [Microsoft’s HTML Help Workshop] (http://www.microsoft.com/en-us/download/details.aspx?id=21138
для построения файла подсказки;
CHM_FILE
Задать имя CHM файла;
CHM_INDEX_ENCODING
=
report.chm.
=
CP1251;
При кодировке UTF-8 не удалось получить корректного
отображения
CHM файла.
Кроме того, были использованы следующие команды форматирования текста и синонимы для них
(в оригинале markdown):
элемент списка (markdown)
начинается с символа минус ’-’ или плюс ’+’;
agp1.fmsd 1.02.10
217
новый параграф (markdown) - начинается пустой строкой;
символ обратная кавычка ’\‘’ начинает и заканчивает небольшой
фрагмент кода (текст, который не надо форматировать);
три минуса подряд с дополнительными символами новой строки (markdown) - начинают и заканчивают
неформатированный текст, вокруг которого рисуется линии;
текст ‘[Doxygen](http://doxygen.org)‘ вставляет в документ
внешние гиперссылки;
текст ‘[Arg](@ref Args.Arg)‘ вставляет в документ
внутренние гиперссылки;
’\\mainpage’
- изменение начальной страницы документа.
\section Тестирование
Для тестирования библиотеки используется специальный
[Тестюнит](@ref test.Program).
*/
/*
-._ ua.NAU.args-0.01/1.08.04 81
===
*/
---- End Of File:./src/csharp/args.txt
Добавление такого файла к отчету дает следующий результат:
agp1.fmsd 1.02.10
218
Рисунок C.1 – Пример использования команд форматирования
текста
D
Диаграммы графов связей Doxygen-а
Диаграммы с частью кода взяты из отчета по проекту [29] и были
построены из следующих классов:
/// \brief класс для демонстрации значений (вводить нельзя)
public class OkDlg : BaseDialog {
...
}
/// \brief родительский класс для диалоговых окон
public abstract class BaseDialog : DialogModel {
protected _TextBox t1;
///< поле ввода
protected Arg[] ps;
protected Size bSz2;
///<это размер поля ввода, в два раза шире стандартной кнопки.
protected Label l1;
///< метка для поля ввода
protected ComboBox cb1;
agp1.fmsd 1.02.10
protected int txtNo;
public _Button OK_but;
. . .
219
///< здесь записано кол-во полей ввода
}
Рисунок D.1 – Пример графа связей класса OkCancelDlg в стиле
Doxygen
agp1.fmsd 1.02.10
Рисунок D.2 – Пример графа связей в стиле UML
220
agp1.fmsd 1.02.10
221
По диаграммам видно, что стрелка означает операцию наследование,
а ромбик – поле документируемого класса. Защищенные члены класса не попадают в диаграмму стиля Doxygen, а на диаграмме стиля
UML помечаются символом номера ’#’.
E
Примеры диаграмм состояний
E.1
Примеры узлов пакета визуализации графов
Исходный код для рис.2.5:
---- File:./src/_dot/sttmchn/nodes.dot
digraph world {
rankdir=LR;
bgcolor=cyan;
size ="6,6";
shape=ellipse;
width=.75;
height=5.5;
subgraph cl{
{rank = same }
// вход в подавтомат
def1[label="",height=.35;width=.35,fixedsize=true];
// выход из подавтомат
def2[shape=ellipse;fontsize=22;label="X",height=.35;width=.35,fixedsize=true];
box3[shape=box, style=rounded, label="submashine",peripheries=2];
box2[shape=box, style=rounded, label="rounded box"];
box[shape=box];
// polygon2[shape=polygon,skew=1.0];
наклоняет
// polygon2[shape=polygon,distortion=1.0]; делает трапецию
diamond [shape=diamond,fixedsize=true];
p [shape=point,width=.3 ];
// вход в автомат
p2 [shape=point,width=.3,peripheries=2];// выход из автомат
}
subgraph cl1{
{rank = source;
Msquare; invtriangle; triangle; polygon; parallelogram;hexagon;octagon}
agp1.fmsd 1.02.10
222
// egg[shape=egg];
Msquare [shape=Msquare,width=.2]
invtriangle[shape=invtriangle];
triangle[shape=triangle];
polygon[shape=polygon,sides=5,fixedsize=true];
parallelogram [shape=parallelogram];
hexagon [shape=hexagon,fixedsize=true];
octagon
[shape=octagon];
}
subgraph cl2{
{rank = sink; box3d; ellipse; Mdiamond; house; tab;
Mdiamond [shape=Mdiamond];
ellipse[label = "ellipse",peripheries=2];
house
tab
box3d
component
plaintext
component; plaintext}
[shape=house];
[shape=tab];
[shape=box3d];
[shape=component];
[shape=plaintext];
}
}
---- End Of File:./src/_dot/sttmchn/nodes.dot
E.2
Примеры стрелок пакета визуализации графов
Исходный код для рис.2.6:
---- File:./src/_dot/sttmchn/edges.dot
digraph world {
rankdir=LR;
edge[arrowhead=none; color=white;]
subgraph a1 {
edge[color=black;]
node [shape=plaintext;label="";]
color=lightgrey;
agp1.fmsd 1.02.10
223
aa->ba[arrowhead=crowtee;
label=crowtee; ];
a->b [arrowhead=normal;
a0->b0[arrowhead=empty ;
a1->b1[arrowhead=invtee;
a2->b2[arrowhead=dot;
a3->b3[arrowhead=halfopen;
a4->b4[arrowhead=odot;
label=normal];
label=empty ];
label=invtee];
label=dot];
label=halfopen];
label=odot];
}
subgraph a2 {
edge[color=black;]
node [shape=plaintext;label="";]
ca->da[arrowhead=crow;
label=crow; arrowtail=dot];
c ->d [arrowhead=crowodot;
label=crowodot; ];
c1->d1[arrowhead=invodot;
c2->d2[arrowhead=none
;
c3->d3[arrowhead=diamond;
c4->d4[arrowhead=ediamond;
c0->d0[arrowhead=normal;
label=invodot];
label=none
];
label=diamond];
label=ediamond];
label=dotted; style=dotted];
}
d->a [arrowhead=invempty; color=blue; label=invempty];
da->aa[arrowhead=inv; color=blue; label=inv];
d0->a0[arrowhead=obox; color=blue;
label=obox];
d1->a1[ color=blue;
dir=back label=back];
d2->a2;
d3->a3;
d4->a4;
}
---- End Of File:./src/_dot/sttmchn/edges.dot
E.3
Диаграмма состояний окна OkCancel
Пример программирования окна ’Ответ на вопрос’(окно OkCancel)
см. [76, 64, Диалоговое окно OkCancel]. Диаграмма состояний для
этого окна представлена на рис. 2.7. Код диаграммы :
---- File:./src/_dot/sttmchn/okcancel.dot
agp1.fmsd 1.02.10
224
digraph world {
//rankdir=RL;
size ="6,4";
subgraph cl{
boxOk
[height=.35 width=0.85 shape=box label=Ok ];
boxCancel[height=.35 width=0.85 shape=box label=Cancel ];
octagon
diamond
start
finish
[shape=box style=rounded label=question?];
[shape=diamond fixedsize=true
// не увеличивать
label=Click];
[shape=point width=.3 ];
// вход в автомат
[shape=point width=.3 peripheries=2]; // выход из автомат
}
start
-> octagon;
octagon
-> diamond [label=button];
diamond
-> boxOk
[label=Ok ];
diamond
-> boxCancel[label=Cancel ];
diamond
-> boxCancel[label=X ];
boxOk
-> finish;
boxCancel -> finish;
}
---- End Of File:./src/_dot/sttmchn/okcancel.dot
Прямоугольникам для действия задается одинаковый размер (в
дюймах)
height=.35 width=0.85
Точно так же, как начальному и конечному состоянию автомата. Атрибут fixedsize запрещает изменять размер узла в зависимости от
текста внутри.
E.4
Диаграмма состояний ’Ввод данных’
Пример программирования окна ’Ввод данных’ см. [76, 64, Диалоговое окно ввод данных]. Диаграмма состояний для этого окна представлена на рис. 2.8. Код диаграммы:
---- File:./src/_dot/sttmchn/datainput.dot
agp1.fmsd 1.02.10
225
digraph world {
boxCheck [height=.35 width=0.85 shape=box label=Check ];
boxOk
[height=.35 width=0.85 shape=box label=Data ];
boxCancel[height=.35 width=0.85 shape=box label=Cancel ];
// можно переходить между полями
octagon [height=.45 width=0.95 shape=box style=rounded
label=Field fixedsize=true];
// поле заблокировано
octagon2 [height=.45 width=0.95 shape=box style=rounded
label="Block Field" fixedsize=true];
// щелчки на кнопках
diamond [shape=diamond fixedsize=true label=Click];
start
[shape=point width=.3 ];
finish
[shape=point width=.3 peripheries=2];
start
-> octagon [label="fields list" ];
// начальные данные
octagon
-> diamond [label=button];
diamond
-> octagon [label="next field"];
diamond
-> boxOk
[label=Ok ];
diamond
-> boxCancel[weight=2 label="Cancel;X" ];
boxOk
-> finish
[weight=80 ];
boxCancel -> finish
[weight=8 ];
// ввод с клавиатуры
diamondInput
[shape=diamond fixedsize=true label="Input"];
octagon
-> diamondInput
[label=keyboard];
// проверка данных
diamondInput
diamondInput
boxCheck
boxCheck
octagon2
octagon2
-> octagon
[label="next field"]; // переход к след.полю
-> boxCheck
[label="data"];
-> octagon
[weight=8 ];
// правильно ввел
-> octagon2
[weight=8 ];
// не правильно ввел
-> diamondInput[weight=8 ];
-> boxCancel
[label="Cancel;X" ];
{rank = min; start;
boxCheck;}
{rank = same; diamond;
octagon2;}
{rank = same; diamondInput; octagon;}
{rank = max; finish; }
}
---- End Of File:./src/_dot/sttmchn/datainput.dot
Если для узла или стрелки требуется метка из нескольких слов, их
требуется взять в двойные кавычки:
start -> octagon [label="fields list" ];
В коде диаграммы узлам задаются некоторые ранги, от минимального до максимального. Ранги влияют на расположение узлов на
диаграмме.
agp1.fmsd 1.02.10
{rank = min; start;
{rank = same; diamond;
E.5
226
boxCheck;}
octagon2;}
Диаграмма состояний главного окна приложения
Пример программирования окна ’Главное окно приложения’ см. [76,
64, Меню в главном окне приложения]. Диаграмма состояний для
этого окна представлена на рис. 2.9. Код диаграммы:
---- File:./src/_dot/sttmchn/mainwndred.dot
digraph mainWindow {
rankdir=TB;
size="8,6";
ratio=fill;
{rank = min; start;
}
start
[shape=point,width=.3 ];
// вход в автомат
subgraph cluster0{
color=red;
window2 [height=.35;width=1.2,fixedsize=true,shape=box, style=rounded, label="Both Windows"];
window [height=.35;width=1.2,fixedsize=true,shape=box, style=rounded, label="Main Window"];
click
[shape=diamond,fixedsize=true,
label="Click"];
work
[height=.35;width=0.85,shape=box,label=Work ];
{rank = same; click; work2}
}
start
start
window
work
click
window2
-> window [color=black; weight=40 ];
-> abtOutX[color=red; ];
-> click ;
-> window2[weight=180 ];
-> work
[label=work,weight=180 ];
-> window ;
subgraph cluster1{
{rank = same; abtIn; abtWnd }
abtIn
[label="",height=.35;width=.35,fixedsize=true];
// вход в подавтомат
abtWnd
[height=.35;width=1.2,fixedsize=true,shape=box, style=rounded, label="About"];
abtClick
[shape=diamond,fixedsize=true,
label="Click"];
abtOutOk
[shape=ellipse;fontsize=22;label="X",height=.35;width=.35,fixedsize=true];
abtOutX
[shape=ellipse;fontsize=22;label="X",height=.35;width=.35,fixedsize=true];
}
agp1.fmsd 1.02.10
abtOutOk
abtOutX
window
abtIn
-> window;
-> window;
-> abtIn [color=red;weight=10 ] ;
-> click[color=red];
abtOutOk->abtClick
abtOutX ->abtClick
abtWnd ->abtIn
abtClick->abtWnd
click
finish
abtIn
}
227
[label=Ok;dir=back];
[label=X;dir=back];
[ dir=back];
[ dir=back];
-> finish [label="File/Exit;X"];
[shape=point,width=.3,peripheries=2]; // выход из автомат
-> click[color=black; dir=back];
---- End Of File:./src/_dot/sttmchn/mainwndred.dot
E.6
Диаграмма состояний главного окна приложения
без подавтомата
Пример программирования окна ’Главное окно приложения’ см. [76,
64, Меню в главном окне приложения]. Диаграмма состояний для
этого окна представлена на рис. 2.10. Код диаграммы:
---- File:./src/_dot/sttmchn/mainwnd1.dot
digraph world {
rankdir=TB;
{rank = min; start;
}
start [shape=point,width=.3 ];
// вход в автомат
subgraph cluster0{
color=white;
window [height=.35;width=1.2,fixedsize=true,
shape=box, style=rounded, label="Main Window"];
click
[shape=diamond,fixedsize=true,
label="Click"];
// добавление-закрытие дочернего окна
work
[height=.35;width=0.85,shape=box,label="Add window" ];
work2 [height=.35;width=0.85,shape=box,label="Close window" ];
{rank = sink; click; work}
{rank = same; window; work2}
}
agp1.fmsd 1.02.10
start
window
work
click
click
work2
// click
228
-> window[color=black; weight=40; label="empty windows list" ];
-> click;
-> window;
-> work
[label=work ];
-> work2
[label="window/X" ];
-> window ;
-> abtIn ;
p2[shape=box, style=rounded, label="About",peripheries=2]
click
-> p2
[weight=20; label=about ] ;
p2
-> window [weight=20 ] ;
click
-> finish [label="file/exit;X"];
finish
[shape=point,width=.3,peripheries=2]; // выход из автомат
{rank = max; finish;
}
}
---- End Of File:./src/_dot/sttmchn/mainwnd1.dot
E.7
Еще одна диаграмма состояний главного окна приложения
Пример программирования окна ’Главное окно приложения’ см. [76,
64, Меню в главном окне приложения]. Диаграмма состояний для
этого окна представлена на рис. 2.11. Код диаграммы:
---- File:./src/_dot/sttmchn/mainwnd2.dot
digraph world {
rankdir=TB;
{rank = min; start;
}
start [shape=point,width=.3 ];
// вход в автомат
{rank = same; window;
work2; click}
window [height=.35;width=1.2,fixedsize=true,
shape=box, style=rounded, label="Main Window"];
click
work
work2
[shape=diamond,fixedsize=true,
label="Click"];
// добавление-закрытие дочернего окна
[height=.35;width=0.85,shape=box,label="Add window" ];
[height=.35;width=0.85,shape=box,label="Close window" ];
agp1.fmsd 1.02.10
finish
[shape=point,width=.3,peripheries=2]; // выход из автомат
{rank = max;
start
window
229
work; finish; p2}
-> window
-> click;
[label="empty windows list"] ;
click
-> finish [label="file/exit;X
"];
click
-> work
[label=work ];
click
-> p2
[label=about ] ;
work
-> window;
click
-> work2
[label="window/X" ];
work2
-> window ;
work -> p2
[color=white; weight=25 ];
window
-> finish [color=white; weight=25 ];
p2[shape=box, style=rounded, label="About",peripheries=2]
p2
-> window ;
}
---- End Of File:./src/_dot/sttmchn/mainwnd2.dot
E.8
Диаграмма состояний дочернего окна представления табличных данных
Пример программирования окна ’Представление табличных данных’
см. [76, 64, Панель инструментов дочернего окна с представлением
табличных данных]. Диаграмма состояний для этого окна представлена на рис. 2.12. Код диаграммы:
---- File:./src/_dot/sttmchn/tbl1.dot
digraph mainWindow {
rankdir=TB;
size="6,4";
ratio=fill;
{rank = min;
start;
}
agp1.fmsd 1.02.10
start
230
[shape=point,width=.3 ];
wnd
// вход в автомат
[height=.35;width=1.2,fixedsize=true,
shape=box, style=rounded, label="Records"];
{rank = same;
click
click;
notReady }
[shape=diamond,fixedsize=true,
label="Click"];
notReady [shape=box, style=rounded, label="Not Ready",peripheries=2]
{rank = max; finish;
}
finish
[shape=point,width=.3,peripheries=2]; // выход из автомат
start -> wnd [label="read table"];
wnd
-> click ;
click -> finish [label="exit;X"];
click -> finish [label="Ok"];
}
---- End Of File:./src/_dot/sttmchn/tbl1.dot
E.9
Диаграмма состояний модального окна отношение
один-ко-многим
Пример похожего окна ’Отношение один-ко-многим’ см. [76, стр.21].
Диаграмма состояний для этого окна представлена на рис. 2.14. Код
диаграммы:
---- File:./src/_dot/sttmchn/1-m2.dot
digraph world {
boxCheck [height=.35 width=0.85 shape=box label=Check ];
agp1.fmsd 1.02.10
//
//
231
boxOk
[height=.35 width=0.85 shape=box label=Data ];
boxCancel[shape=point width=.3 peripheries=2];
finish
[height=.35 width=0.85 shape=box label=Cancel ];
delRec
[height=.35 width=0.85 shape=box label="Del record" ];
// можно переходить между полями
octagon [height=.45 width=1.25 shape=box style=rounded
label="Fields/Recs list" fixedsize=true];
// поле заблокировано
recChc [height=.45 width=1.05 shape=box, style=rounded,
label="Record choice",peripheries=2 fixedsize=true]
octagon2 [height=.45 width=1.25 shape=box style=rounded
label="Block Field" fixedsize=true];
// щелчки на кнопках
click [shape=diamond fixedsize=true label="Click"];
subgraph cluster0{
recChc [height=.45 width=1.25 shape=box style=rounded
label="Fast choice" peripheries=2 fixedsize=true]
click2 [shape=diamond fixedsize=true label="Click2"];
click2 ->
recChc [label=Add];
}
click2->
delRec[label=Del];
start
[shape=point width=.3 ];
boxOk
-> boxCancel;//
[weight=800 ];
boxCancel -> finish [dir=back] ;
start
-> octagon
click
-> delRec
delRec
-> click
octagon
-> click
octagon
-> click2
click
-> boxOk
click
[label="fields and recs list" ];
[color=white weight=5000];
[color=white weight=5000];
[label="top button" weight=5000];
[label="bottom button"];
[label=Ok ];
// начальные данные
-> finish[ label="Cancel;X" ];
click -> octagon2 [color=white];
recChc -> octagon[label="New rec"];
recChc -> octagon[label="Cancel;X"];
// edit -> octagon;
delRec -> octagon;
// ввод с клавиатуры
diamondInput
[shape=diamond fixedsize=true label="Input"];
octagon
-> diamondInput
[ label=keyboard];
// проверка данных
diamondInput
diamondInput
boxCheck
-> octagon
-> boxCheck
-> octagon
[ label="next field"]; // переход к след.полю
[label="data"];
[weight=0 ];
// правильно ввел
agp1.fmsd 1.02.10
boxCheck
octagon2
octagon2
-> octagon2
[weight=5000 ];
-> diamondInput[weight=0 ];
-> finish
[ label="Cancel;X"];
232
// не правильно ввел
{rank = min; recChc; start; boxCheck; }
{rank = same; click2 ;click; delRec;
octagon2;}
{rank = same;
diamondInput;octagon; }
{rank = max; finish; boxOk; boxCancel }
}
---- End Of File:./src/_dot/sttmchn/1-m2.dot
F
Язык формальных спецификаций Z
F.1
Утилита ZTC и язык формальных спецификаций Z
Язык Z описан в документах [20, 17, 57], некоторые примеры из которых обсуждаются ниже. В частности, упоминается спецификации
’Книга Дней Рождений’ которые можно найти в [20, The birthday
book].
F.1.1
Утилита ZTC
Для проверки корректности спецификаций разработано несколько
программных продуктов. Самым простым продуктом для немедленного использования (в отличие от, например, CZT http://czt.sourceforge.
net/) из них оказалась утилита ZTC. Для создания документов и
проверки спецификаций с её помощью потребуется:
• утилита проверки правописания (англ. grammar checker) от Xiaoping
Jia. Её можно загрузить по адресу https://lsi2.ugr.es/~mcapel/
docencia/doctorado/seguro/Zanimacion/, она находится в файле ztcwin.zip;
• Файлы стилей LaTex-а - в дистрибутиве ztcwin.zip находится файл ztc.sty. В разделе 7.2 [19, Installing Windows/MS-DOS
version] этот файл предлагается скопировать в каталог к текущему документу. Стиль oz.sty уже существует в каталоге с
agp1.fmsd 1.02.10
233
TexLive, он расположен по пути /texlive/texmf-dist/tex/latex/objectz.
• Файлы с математическими библиотеками (способы записи математических символов) - mathX.zbx и mathX.zed (X меняется
от 0 до 2 включительно), там же. Их придется держать в каталоге со спецификацией, либо в отдельном каталоге, но тогда это
место нужно задать переменной среды окружения ZLIBPATH.
Все примеры в текущем документе набраны с учетом библиотеки math0.zbx или math0.zbx; Библиотека math0 содержит целые числа Int и много операций для работы работы с ними.
Библиотека math1 добавляет к предыдущей строчки (String)
как последовательность символов и операции, и функции для
работы с плавающими числами (Float): например, сложение
fplus и функцию синуса sin.
SET ZLIBPATH=c:/ztc
В библиотеке math0.zbx находится спецификация целых чисел
Int. Этот тип не является базовым типом языка Z. В библиотеке
math1.zbx находится спецификация вещественных чисел Float,
символов Char, и строчек String;
• руководство по утилите - guide20.pdf (см. [19]);
• в файл преамбулы документа нужно добавить строки
\usepackage{oz,ztc}
это сложный способ работы, или
\usepackage{oz,ztc}
\zedcompatible
более простой способ работы. Разница между ними объясняется ниже;
agp1.fmsd 1.02.10
234
• в некоторых случаях приходится редактировать файлы спецификации в стиле для LaTex-a (см. F.1.1.1 ), чтобы это редактирование выполнять в пакетном режиме, желательно установить
пакетно ориентированный редактор sed.exe ( [21]).
Командная строка утилиты ztc.exe следующая:
---- File:ztc.hlp
This is ZTC (version 2.03)
Usage: ztc [-I[tl]] infile [options]
-I[tl]: set input style
-It: LaTeX
-Il: ZSL
-F: flying erase mode
-L: set the default mode to the liberal mode
-M[0-9]: select mathe library
-Mn: use mathn.zed and mathn.zbx
(default math0.zed and math0.zbx)
-Mlibfile: use libfile.zed and libfile.zbx as math library
-M-: use no math library
-O[tlb]: translate to the output style specified
-Ot: LaTeX
-Ol: ZSL plain text style
-Ob: ZSL box style
-S: suppress type checking
-T: generate type report
-V[0-9]: set verbosity (default 5)
---- End Of File:ztc.hlp
Утилита может выполнять статическую проверку типов и корректность набора спецификации. Поддерживаются три стиля набора
текста спецификации:
• -Ot: LaTeX - несколько трудоемкий и загромождающий взгляд
режим набора командами LaTex (стиль LaTex-а ). Результат
красиво выглядит в документе, которой создан LaTex-ом. Можно выбрать одну из библиотек. Файлы имеют расширение .zed;
agp1.fmsd 1.02.10
235
• -Ol: ZSL plain text style - легко набираемый и читабельный в
текстовом редакторе текстовый стиль спецификации. Утилита
правописания очень чувствительна к символу табуляция (текстовый стиль). Для корректной работы ztc, c табуляции должна начинаться каждая строка спецификации. Такой текст можно использовать в качестве комментариев в текстах программ.
Файлы имеют расширение .zsl;
• -Ob: ZSL box style - рабочий стиль, почти такой же как и предыдущий, но схемы спецификации выделены символами -, а не
ключевыми словами schema, where и end schema (рамочный
стиль). Ниже, рядом с текстом в простом стиле, пример этого
стиля будет приведен. Файлы имеют расширение .zbx.
Кроме того, ZTC может конвертировать спецификацию из одного
стиля в другой.
F.1.1.1 Замеченные недостатки
При использовании Утилиты ztc для построения спецификации в
стиле LaTex-а :
• неудачей заканчивается попытка использовать ключ ’-M’ для
ввода номера математической библиотеки (toolkit) под управлением Windows 7:
-M[0-9]: select mathe library
-Mn: use mathn.zed and mathn.zbx
(default math0.zed and math0.zbx)
-Mlibfile: use libfile.zed and libfile.zbx as math library
Команда
ztc.exe -Il Classman.zsl
-Ot .Classman.zed
приводит к сообщению:
-M1
agp1.fmsd 1.02.10
236
... Initializing.
... Loading Z mathematical tools library: ../etc\math49.zbx
File not found: ../etc\math49.zbx
Parsing main file: Classman.zsl
Утилита пытается подключить файл math49.zbx вместо math1.zbx.
Надо использовать версию ключа с явным указанием имени
файла:
ztc.exe -Il Classman.zsl
-Ot .Classman.zed
-Mmath1.zbx
• табуляции выводится символами ∖tX, где X -цифра. Текущая
версия TexLive в таком случае некорректно отображает текст.
• pdfLatex.exe удаляет пробелы между некоторыми ключевыми
словами, относящиеся к последовательностям и парам (front,
second, etc), и последующим аргументом.
• Символ ’=’ выводится текстом eq.
• С текущей преамбулой не отображается символ пустого множества
\empty
, его приходится заменять на стандартный символ пустого множества
\emptyset
• В разделе F.2.4.10 приводится пример создания шаблона операций, этот пример совместить с утилитой не удается ;(.
• ZTC некрасиво разделяет текст по строкам документа и добавляет лишние скобки.
• ZTC имеет несколько недостатков в отношении использования
действительных чисел. Отчет о способах устранения недостатков см. в [37].
agp1.fmsd 1.02.10
237
При построении текущего документа эти проблемы решались при
помощи потоко ориентированного редактора sed. Далее следует пакетный файл для проверки и конвертации спецификации из простого
стиля в стиль для LaTex-а:
---- File:./src/etc/z.cmd
rem input
rem output
f
f.zed
SET ZLIBPATH=../etc
ztc -Il %1 -Ot .%1 -Mmath1.zbx
sed -f %ZLIBPATH%/z.sed
.%1 >%1.zed
---- End Of File:./src/etc/z.cmd
---- File:./src/etc/z.sed
s/^.t1/~~/
#s/^.t2/~~~~/
s/^.t[3-9]/~~~~~~/
s/ eq /~=~/
s/empty/emptyset/
s/last /\\last /g
s/front /\\front /g
s/head /\\head /g
s/tail /\\tail /g
s/first /\\first /g
s/second /\\second /g
---- End Of File:./src/etc/z.sed
Кроме того, текст спецификации по строкам выводного файла расставляется вручную.
Можно пойти более простым путем (без использования sed.exe),
для этого после подключения пакетов oz.sty и ztc.sty нужно добавить
команду совместимости zed-os:
agp1.fmsd 1.02.10
238
\usepackage{oz,ztc}
\zedcompatible
см.[19, стр.6]. Перечисленные проблемы исчезают, но, к сожалению,
такой режим не совместим с пакетом hyperref, который настраивает
гиперссылки в готовом pdf-документе:
\usepackage[pdftex
pagebackref=true,
colorlinks=true,
linkcolor=blue,
unicode=true
]{hyperref}
И его придется отключить (или отладить).
F.1.1.2 Проверка синтаксиса и первая схема на Z
Рассмотрим спецификацию функции вычисления факториала в
текстовом стиле, которая записана в файле f.zsl:
---- File:./src/etc/f.zsl
spec
schema Factorial
f : N fun N
where
1 = f(0) ;
forall i : N @
end schema
end spec
f(i+1) = f (i) * i+1
---- End Of File:./src/etc/f.zsl
В текстовом стиле спецификация начинается словом spec и заканчивается словом end spec. Спецификация состоит одной или нескольких схем. Схема начинается со слова schema за которым идет имя
схемы, заканчивается словом end schema. В спецификации определяется несколько имен (имя переменной из схемы), определения переменных одно от другого отделяются символом точка с запятой ’;’.
Имя любой схемы не может быть использовано как имя переменной
внутри любой другой схемы. Список определений имен внутри схемы
заканчивается ключевым словом where. За ключевым словом where
начинается раздел предикатов. В приведенном выше примере
agp1.fmsd 1.02.10
239
f : N fun N
f – это имя переменной схемы, N fun N – тип переменной: это всюду определенная функция из множества неотрицательных целых во
множество неотрицательных целых. В разделе предикатов задаются
требования к функции f: на значении 0 функция f принимает значение 1. А для каждого (символ квантор всеобщности forall) неотрицательного i выполняется что f(i + 1) от следующего числа совпадает со значением f(i) от текущего числа i умноженное на i + 1.
Данную схему читать не слишком тяжело. Список часто используемых обозначений в обеих стилях: в текстовом стиле и стиле LaTex
приводится в разделе F.3.
Следующее выполнение командного файла с параметром f
./z.cmd f
должно привести к появлению файла f.zed (подключение файла f.zed
выполнялось командой verbatiminput):
---- File:./src/etc/f.zed
\begin{spec}
\begin{schema}{Factorial}
f : \nat \fun \nat
\where
1 = f (0) \\
\forall i : \nat @ f (i + 1) = f (i) * i + 1
\end{schema}
\end{spec}
---- End Of File:./src/etc/f.zed
Этот файл, будучи включен в отчет как файл LaTex-а (командой
input), начинает выглядеть следующим образом, в привычном математическом стиле:
agp1.fmsd 1.02.10
240
Factorial
f:N→N
1 = f(0)
∀ i : N ∙ f(i + 1) = f(i) * i + 1
F.1.1.3 ZTC и вещественные числа
Язык Z не имеет встроенных вещественных чисел. Тип Float и
связанные с ним функции добавляется в библиотеке math1.zbx (см.
командный файл в разделе F.1.1.1), но не без проблем. Соответствующая часть библиотеки с соответствующими функциями и операциями выглядит следующим образом:
[ Float ]
| ceiling : Float --> Z;
| floor : Float --> Z;
| modf : Float --> Float;
| tofloat : Z --> Float
%% infunl3 fplus
%% infunl3 fminus
%% infunl4 ftimes
%% infunl4 fdiv
| _ fplus _ : Float & Float --> Float;
| _ fminus _ : Float & Float --> Float;
| _ ftimes _ : Float & Float --> Float;
| _ fdiv _ : Float & Float --> Float;
| fneg : Float --> Float
| abs : Float --> Float;
| powerof : Float & Z +-> Float;
| sqrt : Float +-> Float;
| ln, lg : Float +-> Float;
| sin, cos, tan : Float +-> Float;
| arcsin, arccos, arctan : Float +-> Float;
| sinh, cosh, tanh : Float +-> Float
Названия операций достаточно прозрачны и могут быть использованы.
Пример схемы для функции сложения двух вещественных чисел:
---- File:./src/float/spec2.zsl
agp1.fmsd 1.02.10
241
specification
schema sum
sum: Float & Float fun Float
where
forall i,j : Float @ sum (i,j) = i fplus j
end schema
end specification
---- End Of File:./src/float/spec2.zsl
Но используемый пакет для LaTex-а \usepackage{oz,ztc} отображает её не корректно:
sum
sum : × →
∀ i, j :∙ sum(i, j) = ifplusj
Пропал тип Float и операция не отделяется пробелами от переменных. При необходимости использовать вещественные числа вопрос можно решить при помощи редактора SED.
F.1.1.4 Замечания по объемным спецификациям
Достаточно объемные спецификации разрабатываются из отдельных схем (каждая из которых располагается в отдельном файле),
подобно тому как большие приложения состоят из отдельных классов и / или функций. Например, так разрабатывались абстрактная
(неявная) спецификация ’Книга Дней Рождений’ (см. [20, разд.1.2
The birthday book] и разделы F.6, F.7). Для проверки всей спецификации все схемы подключаются к одному файлу bb.zsl командой
input:
---- File:./src/bb/bb.zsl
spec
% сбор всей спецификации
input bbt.zsl
input bbs.zsl
agp1.fmsd 1.02.10
242
input addb.zsl
input fndb.zsl
input rmdb.zsl
input ibb.zsl
input scc.zsl
input akn.zsl
RAddBirthday =^= (AddBirthday
/\
Success)
\/ AlreadyKnown
input raddb.zsl
input nkn.zsl
RFNDB
RRMDB
is
is
( FindBirthday
RMDB and SCC
and Success )
or NKN;
end spec
---- End Of File:./src/bb/bb.zsl
По мере разработки новых схем они подключались к файлу bb.zsl.
Пример файла компиляции спецификации:
---- File:./src/bb/err.lg
Log opened at: Tue Oct 05 14:14:57 2021
... Initializing.
... Loading Z mathematical tools library: ../etc\math0.zbx
Parsing main file: bb.zsl
Include file: bbt.zsl
... Type checking Given set. "bbt.zsl" Line 3
End of file: bbt.zsl
Include file: bbs.zsl
--- Syntax error. "bbs.zsl" Line 6, near "birthday"
Expecting: ’:’ ’,’
>>>birthday
... Type checking Schema box: BirthdayBook. "bbs.zsl" Lines 4-9
End of file: bbs.zsl
Include file: addb.zsl
... Type checking Schema box: AddBirthday. "addb.zsl" Lines 3-10
--- Typing error. "addb.zsl" Line 9. Undefined name: nme?
End of file: addb.zsl
agp1.fmsd 1.02.10
243
Include file: fndb.zsl
... Type checking Schema box: FindBirthday. "fndb.zsl" Lines 3-11
End of file: fndb.zsl
Include file: rmdb.zsl
... Type checking Schema box: Remind. "rmdb.zsl" Lines 3-8
End of file: rmdb.zsl
Include file: ibb.zsl
... Type checking Schema box: InitBirthdayBook. "ibb.zsl" Lines 3-6
End of file: ibb.zsl
Include file: scc.zsl
... Type checking Free type definition: REPORT. "scc.zsl" Line 3
... Type checking Schema box: Success. "scc.zsl" Lines 5-8
End of file: scc.zsl
Include file: akn.zsl
... Type checking Schema box: AlreadyKnown. "akn.zsl" Lines 3-9
End of file: akn.zsl
Include file: raddb.zsl
... Type checking Schema box: RADDB. "raddb.zsl" Lines 3-15
End of file: raddb.zsl
Include file: nkn.zsl
... Type checking Schema box: NKN. "nkn.zsl" Lines 3-9
End of file: nkn.zsl
... Type checking Schema definition: RFNDB. "bb.zsl" Line 16
End of main file: bb.zsl
... Translating to LaTeX style
Output written in ".bb.zsl"
Log written in "bb.log"
Log closed at: Tue Oct 05 14:14:58 2021
---- End Of File:./src/bb/err.lg
Файл содержит сообщения о двух ошибках. Интерпретация этих сообщений несколько, гм, непривычна, но ошибки исправляются довольно легко.
--- Syntax error. "bbs.zsl" Line 6, near "birthday"
Expecting: ’:’ ’,’
В 6й строчке схеме bbs.zsl обнаружена ошибка возле слова "birthday".
Для создания ошибка в схему был добавлен лишний символ ’a’:
known
: P NAME; a
birthday : NAME pfun DATE
% ошибочный символ a
agp1.fmsd 1.02.10
244
... Type checking Schema box: AddBirthday. "addb.zsl" Lines 3-10
--- Typing error. "addb.zsl" Line 9. Undefined name: nam?
В 9й строке схемы addb.zsl ссылка на не описанное имя ’nam?’ (должно быть ’name?’):
schema AddBirthday
Delta BirthdayBook;
name? : NAME;
date? : DATE
where
nam? notin known ;
F.1.2
% ошибочное имя, пропущена буква e
Z и описание данных
Языки формальных спецификаций можно использовать, кроме их
прямого предназначения, для формального описания входных - выходных данных.
F.1.2.1 Имя
В следующей схеме описывается имя: последовательность цифр,
букв и символов подчерка, которая начинается с буквы или символа
подчерка.
---- File:./src/data/name.zsl
spec
schema name
digits : P Char; % 48..57 would be better
% underscore : {ascii_char(95)}
;
letters: {le: P Char | forall l: le @ ascii_of (l) in 97..122 and # le = 26 }; % all the letters
Letters: {LE: P Char | forall l: LE @ ascii_of (l) in 65..90 and # LE = 26 } ;
char
: P Char ;
Name
: seq1 Char;
where
digits = {’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, ’8’, ’9’};
char =
Letters setunion letters setunion digits
setunion {ascii_char(95)};
ran Name subset char
and
head Name in char setminus digits ;
end schema
end spec
agp1.fmsd 1.02.10
245
---- End Of File:./src/data/name.zsl
В схеме использованы следующие обозначения:
• разность множеств setminus ;
• множество определения отображения ran;
• функция ascii char : N → Char, которая по коду числа возвращает его символ. Функция входит в математическую библиотеку math1.zbx;
• символ непустой последовательности: seq1;
• квантор всеобщности forall;
• функция мощности множества #, она возвращает количество
элементов конечного множества;
• функция head, которая возвращает первый символ последовательности Name;
• функция ran, которая возвращает множество значений отображения Name.
В ней определено
• множество маленьких букв латинского алфавита: letters;
• затем – больших букв латинского алфавита: Letters;
• затем – цифр: digits;
• затем – множество букв, цифр и символов подчеркивания: char
(ascii char(95) - это символ подчеркивания);
• затем, собственно, само имя: множество значений последовательности включается во множество всех символов char (буквы, цифры и подчеркивания), а начало последовательности либо буква, либо подчеркивание.
agp1.fmsd 1.02.10
246
Эта же схема стиле LaTex-а выглядит следующим образом:
name
digits : P Char
letters : {le : P Char | ∀ l : le ∙ (ascii of(l) ∈ 97 . . 122 ∧ #le = 26)}
Letters : {LE : P Char | ∀ l : LE ∙ (ascii of(l) ∈ 65 . . 90 ∧ #LE = 26)}
char : P Char
Name : seq1 Char
digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
char = Letters ∪ letters ∪ digits ∪ { ascii char(95)}
ran Name ⊂ char ∧ head Name ∈ char ∖ digits
F.1.2.2 Текстовое представление целого числа
Целое число – это не пустая последовательность цифр, которая
возможно начинается с символа ’-’ или ’+’ (см. раздел [75, Текстовое
представление целых чисел]).
---- File:./src/data/int.zsl
spec
schema IntN
digits : P Char ;
IntN
: seq1 Char;
where
digits = {’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, ’8’, ’9’};
let od ==
(if head IntN in {’-’, ’+’}
then ran (tail IntN)
else ran IntN) @
# od > 0 and od subset digits
;
end schema
end spec
---- End Of File:./src/data/int.zsl
В спецификации задано множество цифр: digits и используется выражение let. Выражение let (см. [20, стр.71]) читается следующим образом: пусть od (only digits) обозначает множество значений (функция
agp1.fmsd 1.02.10
247
ran от слова range) последовательности, в которой удалили лидирующий символ ’+’ или ’-’, в случае его наличия, (функция tail (см.
[20, стр.117]) ) тогда она не пустая и состоит только из цифр.
Замечание
Последовательность S (см. [20, стр.115]) можно трактовать как
частично определенную функцию на множестве натуральных
чисел. Тогда у неё определены множество определения dom S
и множество значений ran S (см. [20, стр.101]).
Эта спецификация в стиле LaTex :
IntN
digits : P Char
IntN : seq1 Char
digits = {0, 1, 2, 3, 4,
5, 6, 7, 8, 9}
let od == (if head IntN ∈ {−, +}
then ran(tail IntN) else ran IntN) ∙ (#od > 0
∧
od ⊂ digits)
F.1.2.3 Текстовое представление вещественного числа
Вещественное число – это не пустая последовательность цифр и
не более чем одного символа точка ’.’, которая возможно начинается с символа ’-’ или ’+’ (см. раздел [79, Текстовое представление
вещественных чисел]).
---- File:./src/data/double.zsl
spec
schema DoubleN
digits
: P Char ;
DoubleN
: seq1 Char;
where
agp1.fmsd 1.02.10
248
digits = {’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, ’8’, ’9’};
let od ==
(if head DoubleN in {’-’, ’+’}
then ran (tail DoubleN)
else ran DoubleN)
@
# od > 0
and
od subset digits
and # ( dom (DoubleN |> {’.’})) <= 1
end schema
end spec
%
and # { DoubleN ~ (’.’)} <= 1
---- End Of File:./src/data/double.zsl
В этой схеме было использовано новое обозначение:
RBS
Пусть R – некоторое отображение, тогда его можно уменьшить ограничением множества значений на S – подмножества множества значений R: SsubsetranR. Множеством значений нового отношения становится S, при этом в множестве определений нового отображения
остаются только те, значения которые отображаются в S (см. [20,
стр.98]). Далее, мощность множества определений новой последовательности не более чем 1. То есть, количество индексов в исходной
строке, которым соответствует символ точка ’.’, не более чем 1.
Замечание
Условие того, что символ точка входит в последовательность
не более одного раза можно записать при помощи прообраза
отображения следующим образом:
#DoubleN (′ .′ ) <= 1
Но к этой записи есть замечание. Обратное отображение DoubleN∼
примененное к любому символу может возвращать множество.
Например, для числа d =′ 1.11′ , обратное отображение d∼′ 1′
совпадает с множеством { 0, 2, 3 }. Однако проверка типов утилиты ztc утверждает, что это просто целое. Приходится ставить
лишние фигурные скобки вокруг применения обратного отображения к символу точка: DoubleN (′ .′ ).
agp1.fmsd 1.02.10
249
Эта спецификация в стиле LaTex :
DoubleN
digits : P Char
DoubleN : seq1 Char
digits = {0, 1, 2, 3, 4,
5, 6, 7, 8, 9}
let od == (if head DoubleN ∈ {−, +}
then ran(tail DoubleN) else ran DoubleN) ∙ (#
od > 0 ∧
od ⊂ digits ∧
#(dom(DoubleN B {.})) ≤ 1)
F.2
Введение в язык Z
Этот раздел по большей части представляет собой перевод одной из
глав работы Jonathan Bowen-а, см. [15, A Brief Introduction to Z].
F.2.1
Логика предикатов
Формальным базисом для Z является логика предикатов первого порядка (predicate logic) и теория типов. Логика будет обсуждаться
очень кратко, так как на практике большинство спецификаций на
языке Z используют её символы достаточно ограниченно.
F.2.1.1 Логика высказываний
Логика высказываний является подмножеством логики предикатов.
Далее перечисляются обычные операции над логическими значениями (true / false):
• отрицание (¬ p) – унарная операция, для вычисленного значения выражения p (true / false), возвращает обратное (false/
true);
agp1.fmsd 1.02.10
250
• логическое И (p ∧ q) – возвращает true, если оба ыражения
являются true, иначе – false;
• логическое ИЛИ (p ∨ q) – возвращает true, если одно из выражений является true, иначе – false;
• следует (p ⇒ q) – определяется как ¬ p ∨ q. Интуитивно, если
p вычисляется как true, то и q должно вычисляться как true,
в другом случае q может иметь любое значение.
• логическая эквивалентность (p ⇔ q) – является сокращением
для p ⇒ q ∧ q ⇒ p. Если оба выражения p и q имеют одинаковое значение, то все выражение вычисляется как true, в
противном случае – false.
F.2.1.2 Квантификация
Логика предикатов отличается от логики высказываний наличием
кванторов на множестве значений (в языке Z, при этом учитывается
тип значений):
• квантор всеобщности ∀ X ∙ q – выполняется только тогда, когда
выполняется предикат q для всех возможных значений X;
• квантор существования ∃ X ∙ q – выполняется только тогда,
когда существует (хотя бы одно) значение из X для которого
выполняется предикат q. Таких значений может быть больше
чем одно, к примеру, все возможные значения из квантора всеобщности удовлетворяют квантору существования;
• квантор существования и единственности ∃1 X ∙ q – это специальный случай более общего квантора существования. Он
утверждает, что существует точно одно значение, для которого выполняется предикат q.
В каждом из приведенных случаев, X обозначает множество значений заданного типа. В этих же примерах область использования
agp1.fmsd 1.02.10
251
значений X ограничено предикатом q. Таким образом, если понадобится, эти же имена (обозначения) могут быть использованы за
пределами фразы для обозначения других величин.
F.2.1.3 Законы
Существует широкий набор алгебраических законов для преобразования предикатов во время доказательств утверждений о спецификациях. Большая часть из них можно найти в работе [7]. В этом
документе изложено весьма беглое введение в логику предикатов.
Подробности можно прочитать в работе [18].
F.2.2
Множества и отношения
Исчисление предикатов первого порядка образует логическую основу языка Z. Теория множеств является еще одним важным аспектом Z. Объединение этих разделов дискретной математики является
очень полезным для формального описания компьютерных систем.
Z использует понятие типов. Этот раздел начинается с объяснения
почему использование типов очень важно для спецификаций. Далее
вводятся понятие множества и операции над множествами. Завершается раздел обсуждением отношений между элементами множеств.
F.2.2.1 Типы
Z является типизированным языком; то есть, каждая переменная
в Z имеет конкретный тип (другими словами – множество, значения
из которого могут быть присвоены данной переменной).
Первый вопрос, который возникает по этому поводу: зачем вообще нужны типы? Они влекут дополнительные усложнения в спецификации. Однако далее объясняется какие причины влекут полезность типов:
• Типы помогают структурировать спецификацию.
agp1.fmsd 1.02.10
252
Они позволяют указать множество допустимых значений для
переменной и затем, если потребуется, высказывать дополнительные ограничения при помощи предикатов. Например, на
русском языке:
пусть x путь наименьшей длины (least cost) из A в B
Тогда можно присвоить тип переменной x:
x: Path
и далее, ограничить её при помощи предиката:
least_cost x
• Типы облегчают разработку кода по спецификации.
В конце – концов, любую переменную спецификации потребуется реализовать как переменную соответствующего типа из
языка программирования. Имеет смысл задуматься над этим
на ранних стадиях разработки. Более того, находить и исправлять ошибок в спецификациях проще и быстрее, чем во время
кодирования.
• Типы позволяют избегать бессмысленных спецификаций.
Типы облегчают проверку спецификаций на непротиворечивость как человеческим просмотром, так и программным способом, при помощи утилит проверки правописания. Например,
дано, что Z : Methods, а Jonatan : People, очевидно, что бессмысленно говорить
Z = Jonathan
Итак, рассмотрим использование предикатов в спецификации:
agp1.fmsd 1.02.10
253
A, B : People
x : Likes
Predicate(x)
Первая часть спецификации называется сигнатурой (переменных
включая типы), вторая часть – предикатом. Часть сигнатуры после
двоеточия задает тип переменных перед двоеточием. Это похоже на
определение в таких языках программирования как Pascal. Как строить типы и использовать переменные в предикатах будет понятно
после изучения теории множеств.
Замечание
Ниже окажется, что типы – это специальные множества. И все
другие множества составляются из элементов одного типа.
F.2.2.2 Множества
В начале 20-го столетия математики выяснили как создавать мир
множеств, мощный достаточно, чтобы описывать все что можно встретить вокруг.
Множество является коллекцией элементов некоторого типа.
Замечание
Определение несколько противоречит определению типа из предыдущего раздела. По предыдущему разделу, если элементы принадлежат одному множеству, то они уже одного типа (:))).
Далее следуют некоторые примеры как в языке Z записываются множества:
• ∅ – это обозначение пустого множества, то есть, такого, которое не содержит элементов. Еще его можно обозначать фигурными скобками: {}.
agp1.fmsd 1.02.10
254
• {Jane, Alice, Emma} – это множество из трех человек. Нужно
заметить, что типы у Jane, Alice и Emma должны быть совместимы.
• {0, 1, 2} = {0, 0, 1, 0, 2, 1} = {1, 2, 0} – все эти способы записи представляют одно и тоже множество трех чисел. Важным
свойством множеств является неупорядоченность элементов (в
отличие от списков). Таким образом, числа в примере могут
быть перечислены в любом порядке, а повторяющиеся элементы считаются одним.
• {0, 1, 2, . . .} – это множество натуральных или целых чисел
больше или равных 0. Множество содержит бесконечное количество элементов. Символ . . . в этом определении не является
формальным, то есть, не является частью языка Z. Нет возможности перечислить все элементы этого множества в такой
записи. Позже для преодоления этой трудности будет введен
соответствующий способ записи. Так как множество натуральных чисел очень важно в спецификациях, в языке Z для него
ввели специальное обозначение – символ N.
Замечание
0 – не считается натуральным числом. Таким образом,
это определение в языке Z не слишком корректно.
• {∅} ̸= ∅ очень важно понимать, что множество состоящее из
пустого множества отлично от пустого множества. Оно содержит один элемент (именуемым пустым множеством). Таким образом, существует возможность составлять множество из других множеств. Это будет рассмотрено позже.
Нужно отметить, что каждое множество может иметь некоторый
базовый тип (basic type) или быть выведено из данного множества
(given set) в Z. Это утверждение применяется к пустому множеству.
agp1.fmsd 1.02.10
255
Таким образом, существуют различные пустые множества для каждого типа. Если пустое множество используется в Z, его тип должен
быть очевиден из контекста. Невозможность определить тип пустого множества является следствием проблем в спецификации. Чтобы
избежать неоднозначности используется запись ∅[T].
Очень важна возможность записать что этот элемент принадлежит конкретному множеству. Это записывается следующим образом:
x∈S
Запись так же является предикатом (дополнительным ограничением) для x и S. Нужно заметить, чтобы это утверждение имело смысл,
эти x и S должны быть совместимы по типу. Далее записаны некоторые примеры этого обозначения:
• 0 ∈ {0, 1, 2, . . . } – очевидно что это правда, так как 0 является
одним из элементов множества, которое содержит 1, 2, 3.
• ∅ ∈ {∅} – пустое множество заданного типа, является элементом множества, которое содержит пустое множество этого
типа.
• 0 ̸∈ ∅ – по-другому, это утверждение записывается как ¬ 0 ∈
∅, 0 не является элементом пустого множества, так как, в пустом множестве вообще нет элементов по определению. На деле, это можно записать для любого x.
• William ̸∈ {Jane, Alice, Emma}.
F.2.2.3 Операции над множествами
К этому моменту уже был обсужден способ записи конечных множеств и способ записи принадлежности или не принадлежности элемента ко множеству. Этих возможностей не достаточно, чтобы получать пользу. Необходим более богатый набор операций на множествах.
Как из двух множеств сделать одно:
agp1.fmsd 1.02.10
256
• P ∪ Q – объединение множеств (англ. union). Операция возвращает множество, которое состоит из элементов множества
P, или множества Q или обеих. Можно заметить, что запись
{a, b, c, . . . } является сокращенной формой для записи
{a} ∪ {b} ∪ {c} ∪ . . .
• P ∩ Q – пересечение множеств (англ. intersection). Операция
возвращает множество, которое состоит из элементов, которые
принадлежат множеству P и множеству Q. Можно заметить,
что запись {a, b, c, . . .} является
• P ∖ Q – разность множеств (англ. difference). Эта операция возвращает множество из элементов P, которые не принадлежат
множеству Q.
Далее, обсуждаются предикаты на множествах:
• P = Q – эквивалентность множеств. Множество P и Q состоят
из одних и тех же элементов. Как уже обсуждалось раньше:
{Alice} = {Alice, Alice, Alice}
{Alice, Emma} = {Emma, Alice}
Для предыдущих три операций выполняется:
P∖Q∪P∩Q∪Q∖P=P∪Q
• Часто требуется высказать отрицание эквивалентности множеств: то есть, что P и Q различаются хотя бы одним элементом. Это можно записать следующим способом: P ̸= Q или,
что тоже самое ¬ (P = Q)
• P ⊆ Q – множество P включается в Q, то есть, является подмножеством. Это означает, что все элементы P содержатся в
Q. Причем может быть случай, когда P и Q – эквивалентны.
Чтобы указать строгое включение используется запись P ⊂ Q.
Это сокращенная форма записи P ⊆ QP ̸= Q.
agp1.fmsd 1.02.10
257
• Следующая операция возвращает дополнение (complementation)
ко множеству P: P− . Теория множеств содержит идею всех элементов, которые не содержатся в данном множестве – дополнение. Так как Z типизированный язык, это подразумевает все
элементы того же типа, что и в исходном множестве. Пусть
для некоторого типа T выполняется P ⊂ T, P− = T ∖ P. Кроме
того, T− = ∅[T] и ∅[T]− = T
• Осталось еще раз упомянуть операцию принадлежности ко множеству: x ∈ P – элемент x является одним из элементов множества P и напротив x ̸∈ P – x не является одним из элементов
множества P.
F.2.2.4 Обобщение операций над множествами
Операции объединения и пересечения множеств могут быть обобщены, то есть, они могут применяться к бесконечному количеству
множеств, а не только к двум. Полуформально это выглядит следующим образом:
⋃︀
{A, B, C, . . . } = A ∪ B ∪ C ∪ . . .
⋂︀
{A, B, C, . . . } = A ∩ B ∩ C ∩ . . .
F.2.2.5 Сокращенное определение множества
До этого раздела множества определялись только прямым перечислением его элементов. Это очень ограниченный, хотя часто полезный способ определения множеств. Так как обычно множества
содержат гораздо больше, чем два – три элемента, то такой способ
на практике оказывается слишком громоздким. А для бесконечных
множеств – он не применим вообще.
Таким образом, для определения любых множеств требуется более общая конструкция. Она называется сокращенное определение
множества (set comprehension) и имеет следующий вид:
{x : Type|predicate(x)}
agp1.fmsd 1.02.10
258
Замечание
Таким образом, как было замечено в конце разделе про типы (см. F.2.2.1), любое множество строится из элементов некоторого специального и самого ’большого’ множества, которое
называется типом.
Более общий вид: {Signature|Predicat}, причем в Signature может
упоминаться более одной переменной.
Далее, несколько примеров использования сокращенного определения множеств:
{x : N|x is prime}
эквивалентное перечисление
{2, 3, 5, 7, 11, 13, . . . }
Это определение множества всех простых чисел. Оно, естественно
бесконечное (см. https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%
BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%95%D0%B2%D0%BA%D0%BB%D0%B8%D0%
B4%D0%B0).
{x : Path|x least cost}
– определяет множество путей между пунктами A и B с минимальной стоимостью. Может быть больше чем один путь и все стоят одинаково или множество может быть пустым если между этими пунктами вообще нет пути.
{x : Methods|Jonathan uses x}
– определяет множество методов, которые использует Jonathan. Оно
может быть пустым. Сомнительно чтобы оно было бесконечным, хотя может быть достаточно большим. Обратите внимание, что в Z
можно использовать подчеркивание.
agp1.fmsd 1.02.10
259
F.2.2.6 Подмножества
Далее потребуется идея подмножества – то есть, множества, которое содержится внутри другого. Рассмотрим несколько примеров:
• A ⊆ B : каждый элемент A является элементом B.
• ∅ ⊆ A : это выполняется всегда, каждое множество включает
в себя пустое подмножество, соответствующего типа.
• A ⊆ A : каждое множество включает себя самого.
• {0, 1} ⊆ N : числа 0 и 1 являются подмножеством множества
натуральных чисел.
• {x : N|x is prime ∧ x ̸= 2} ⊆ {x : N|x is odd} : множество
простых чисел отличных от числа 2 является подмножеством
нечетных чисел.
F.2.2.7 Множества и высказывания
Множества и высказывания несколько похожи друг на друга. Любой операции на множествах соответствует логическая связка, которая ассоциируется с операцией. Например, как связаны между собой
пересечение множеств (∩) и логическое И (∧) показано ниже, при
этом, p и q – некоторые высказывания (в которых используется x):
{x : T|p} ∩ {x : T|q} = {x : T|p ∧ q}
Таким же образом похожи объединение множеств (∪) и логическое
ИЛИ (∨):
{x : T|p} ∪ {x : T|q} = {x : T|p ∨ q}
Дополнение является множеством, которое соответствует отрицанию
высказывания:
{x : T|p}− = {x : T|¬ p}
agp1.fmsd 1.02.10
260
Нужно заметить, что во всех формулах выше T является типом, это
важно.
Обозначению подмножества (⊆) соответствует логическое следование (⇒):
{x : T|p} ⇒ {x : T|q} iff p ⇒ q
Равенству множеств (=) соответствует логическая эквивалентность
(⇔):
{x : T|p} = {x : T|q} iff p ⇔ q
Пустому множеству (соответствующего типа T) соответствует высказывание false:
∅[T] = {x : T| false}
Всему множеству элементов заданного типа соответствует высказывание true:
∅[T] = {x : T| true}
F.2.2.8 Опять про операции над множествами
Рассмотрим операцию включения ⊆. Она обладает несколькими
математическими свойствами. Для подмножеств типа T: P, Q и R
(то есть, P ⊆ T, Q ⊆ T и R ⊆ T) выполняется:
• ⊆ рефлексивно: P ⊆ P
• ⊆ транзитивно: (P ⊆ Q ∧ Q ⊆ R) ⇒ P ⊆ R
• ⊆ антисимметрично: (P ⊆ Q ∧ Q ⊆ P) ⇒ P = Q
• ∅[T] является минимальным множеством в T: ∅[T] ⊆ P, то
есть, оно является подмножеством любого другого подмножества из T
agp1.fmsd 1.02.10
261
Подобными свойствами обладает и операция пересечение (∩): ∩
является наибольшей нижней границей операции включения ⊆ –
R ⊆ P ∧ R ⊆ Q ⇔ R ⊆ (P ∩ Q)
то есть, P ∩ Q является наибольшим подмножеством, которое содержится в P и Q.
Далее, ∩ является
• идемпотентной: P ∩ P = P
• симметричной: P ∩ Q = Q ∩ P
• ассоциативной: (P ∩ Q) ∩ R = P ∩ (Q ∩ R)
• монотонной: P ⊆ Q ⇒ (R ∩ P) ⊆ (R ∩ Q)
Далее, независимо от типа можно писать P− для дополнения к P.
И дополнение ко множеству является обратимой операцией: (P− )− =
P. А так же,
P ⊆ Q ⇔ Q− ⊆ P−
и
P ⊆ Q ⇔ P ∩ Q− = ∅
Кроме того, вследствие закона Моргана вместо (P− ∩Q− )− пишут
P ∪ Q. Более подробный список законов можно посмотреть в [20].
F.2.2.9 Прямое произведение множеств
Часто для построения составных типов могут использоваться два
или более множеств Можно говорить, что ассоциируются два или
более множества. Пусть T и U – некоторые типы, тогда прямое произведение (декартово произведение):
T×U
agp1.fmsd 1.02.10
262
обозначает тип из упорядоченных пар (t, u), где t : T и u : U. Если
P и Q являются подмножествами типов T и U соответственно, то
P × Q = {(p, q)|p ∈ P ∧ q ∈ Q}
Обозначение обобщается на любую упорядоченную n-ку (кортеж):
E1 × E2 × . . . × En
Далее приводятся примеры как используются обозначения упорядоченной пары и прямого произведения:
(Z, Jonathan) ∈ Methods × People
При помощи пары метод Z ассоциирован (поставлен в соответствие)
человеку с именем Jonathan.
(Oxford, Cambridge) ∈ Places × Places
Элементы пары могут быть одинакового типа.
(Jonathan, Oxford, 1956) ∈ People × Places × N
Эта тройка является примером как можно указать место и год рождения человека.
Функции для извлечения первого или второго компонента пары
будут обозначаться следующим образом:
first(t, u) = t
second(t, u) = u
Для каждой упорядоченной пары t выполняется равенство:
(first t, second t) = t
agp1.fmsd 1.02.10
263
F.2.2.10 Пересмотр сокращенного определения множества
Вспомним, что сокращенное определение множества имеет вид
{Signature|Predicate}
Например:
{x : Methods; y : People|Jonatan uses x ∧ xapproved by y}
Эта сигнатура образует упорядоченную пару типа Methods × People.
Порядок в паре – важен. Таким образом, пара x : Methods; y : People
отлична от пары y : People; x : Methods. Вторая сигнатура будет
образовывать пары в порядке, противоположном к первой.
Может потребоваться частичная сигнатура при сокращенном определении множества. Вообще говоря
{x1 : X1 ; . . . ; xn : Xn |Predicate}
это то же самое, что и
{x1 : X1 ; . . . ; xn : Xn |Predicate ∙ (x1 , . . . , xn )}
Этот способ записи позволяет записывать более сложные множества. Например, множество квадратов простых чисел может быть
определено как:
{x : N|x is prime ∙ x * x}
В этой записи именно выражение x*x задает определение множества.
В общем случае последнее выражение после символа ’∙’ может
быть любым допустимым выражением:
{Signature|Predicate ∙ Expression}
Сигнатура задает тип величин, которые требуются для сокращенного определения множества, предикат ограничивает их и выражение
определяет элементы в желаемом множестве. В случае, если требуются только n-ки, формируемые компонентами сигнатуры, выражение можно опускать. Так же можно опустить предикат, если он
всегда выполняется.
agp1.fmsd 1.02.10
264
F.2.2.11 Степень множества
Тип переменной, которая является множеством, является множеством множеств. Наличие переменных в спецификациях на языке
Z являются множествами влечет необходимость иметь специальное
обозначение для них. Если S является множеством, то P S обозначает множество всех подмножеств S и называется булиан (или степень
множества, англ. power set) S. При этом,
X∈PS⇔X⊆S
При этом ∅ ∈ P S, таким образом, P S ̸= ∅.
Далее, приведем несколько примеров степени множества:
• P ∅ – это множество просто состоит из пустого множества данного типа, то есть, P ∅ = {∅};
• P {0} – степень множества, состоящего из одного элемента, состоит из пустого множества данного типа и самого этого множества из одного элемента, то есть, P {0} = {∅, {0}};
• P N – это множество всех подмножеств натуральных чисел,
естественно оно бесконечное:
• P Path – множество всех путей из одного пункта в другой;
• P (N × N) – множества различных отношений между натуральными числами;
• S == P((Places×Places)×Path) – таким образом определяется
аббревиатура, X == Y означает замени вхождение X на Y везде, где X будет далее использовано. Тут используются скобки,
чтобы сгруппировать прямые произведения (скобки можно использовать достаточно много раз, но лучше не злоупотреблять,
чтобы не пострадала читабельность текста);
Такое определение множества S дает возможность использовать
запись вроде 𝜋 ∈ S. Символы подчеркивания (англ. under score)
agp1.fmsd 1.02.10
265
указывают место для двух аргументов инфиксной операции, где 𝜋 –
её символ. При этом левый операнд имеет тип (Places × Places), а
правый – тип Path.
Как было отмечено выше, булиан может содержать бесконечные
множества. Если есть специальный интерес к конечным множество,
необходимо использовать другой символ языка Z. Если S множество,
то F S обозначает множество всех конечных подмножеств S.
Иногда требуется исключить пустые множества из рассмотрения.
В таких случаях используются обозначения P1 и F1 , где:
P1 S == P S ∖ ∅
F1 S == F S ∖ ∅
F.2.2.12 Отношения
Достаточно часто элементы одного множества каким – то образом
связаны с элементами другого множества. Например:
• соседние адреса;
• маршрут и стоимость переезда по нему;
• маршрут из A в B минимальной стоимостью.
Все эти примеры являются отношениями (предикатами с двумя операндами). Таким образом, отношение R между множествами P иQ
является подмножеством прямого произведения P × Q:
R⊆P×Q
.
Примеры, приведенные выше, можно несколько формализовать:
• (A, B) ∈ R1 iff A, B – соседние;
• (x, y) ∈ R1 iff путь x стоит y;
agp1.fmsd 1.02.10
266
• ((A, B), P) ∈ R3 iff P является минимальной ценой пути из A
в B.
Если R является отношением между P и Q, можно писать p R q
вместо (p, q) ∈ R. Далее, будем писать R чтобы указать, что отношение является инфиксным (бинарным). Кроме того, можно использовать функциональный вид записи (англ. maplet notaion)
p ↦→ q вместо (p, q)
чтобы подчеркнуть отображение p в q. Математический смысл при
этом не меняется.
Еще дополнительные примеры отношений и обозначений, связанных с ними:
≤ = {x, y : N|(∃ z : N ∙ x + z = y)}
uses = {Jonatan ↦→ Z, Peter ↦→ VDM, Peter ↦→ RAISE}
Если T, U это типы, то
T ↔ U == P(T × U)
обозначает множество всех отношений между T и U. Например,
≤ ∈N↔N
uses ∈ {Jonatan, Mike, Peter} ↔ Methods
Каждое отношение имеет область определения (англ. domain) и
множество значений (англ. range). Область определения отношения
R : T ↔ U это множество всех элементов из T, для которых в R
существует по крайней мере один элемент из U. Множество значений
отношения R : T ↔ U это множество всех элементов из U, для
которых в R существует по крайней мере один элемент из T. Точнее:
dom R = {x : T|(∃ y : U ∙ (x, y) ∈ R)}
agp1.fmsd 1.02.10
267
ran R = {y : U|(∃ x : T ∙ (x, y) ∈ R)}
Для каждого отношения существует обратное (англ. inverse relation).
Обратное отношение это такое множество двоек (y, x) в которых
компоненты двоек (x, y) исходного отношения расположены в обратном порядке. Формально записывается следующим образом:
R∼ = {x : T, y : U|(x, y) ∈ R ∙ (y, x)}
= {x : T, y : U|(x, y) ∈ R ∙ y ↦→ x}
= {x : T, y : U|(x, y) ∈ R}
Если R имеет тип T ↔ U, то его обратное отношение R∼ имеет
тип U ↔ T.
Замечание
Обратное отношение R∼ можно записывать как R−1 для некоторых отношений. А именно, когда область определения и множество значений имеют некоторый одинаковый тип X: R : X ↔
X.
В качестве примеров для отношения использует (’uses’) можно
написать:
dom uses = {Jonathan, Peter}
ran uses = {Z, VDM, RAISE}
uses∼ = {Z ↦→ Jonathan, VDM ↦→ Peter, RAISE ↦→ Peter}
Еще несколько примеров использования только что введенных
обозначений:
ran
≤ = dom
≤ =N
agp1.fmsd 1.02.10
268
( ≤ )∼ = ≥
Следующие равенства связывают область определения, множеством
значений и обратное отношение:
ran (R)∼ = dom R
dom (R)∼ = ran R
(R∼ )∼ = R
С другой стороны, обсуждения отношений подобны обсуждению множеств.
F.2.3
Функции и операции над ними
К этому моменты были обсуждены обозначения языка Z, имеющие
отношения ко множествам и отношениям. Далее, будет рассмотрен
такой важный класс отношений как функции и операции, которые
можно применять к отношениям и функциям.
F.2.3.1 Функции
В языке Z функцией называется специальное отношение, в котором каждому элементу из области определения соответствует не более одного элемента из множества значений. Для примера, напишем
формальное определение частичной функции →
↦ используя сокращенное определение множества в терминах отношений ↔:
X→
↦ Y == {f : X ↔ Y|(∀ x : X; y1 , y2 : Y∙
(x ↦→ y1 ) ∈ f ∧ (x ↦→ y2 ) ∈ f ⇒ y1 = y2 )}
то есть, любой элемент x области определения можно отобразить в
не более чем один элемент множества значений. В этом определении
agp1.fmsd 1.02.10
269
буквы X и Y являются идентификаторами, которые обозначают случайные формальные шаблоны параметров (англ. generic parameters).
Они используются в правой части определения. Символ →
↦ является
инфиксным и X →
↦ Y сокращенной формой записи ( →
↦ ){X, Y},
где символы подчеркивания ( ) указывают места операндов. При использовании стрелки X →
↦ Y и других конструкций шаблоны параметров могут быть явно записаны в квадратных скобках, но обычно
квадратные скобки пропускают в большинстве случаев, так как они
очевидны из контекста и загромождают спецификацию.
В Z существует набор специальных типов функций, каждый тип
задается своей собственной стрелкой:
• X → Y – всюду определенные функции;
• X ↦ Y – частичные иньекции – взаимно однозначные отображения между элементами области определений и множества
значений, обратное отображение тоже является функцией;
• X Y – всюду определенные иньекции – взаимно однозначные отображения между элементами множества определений и
множества значений, функция определена для каждого элемента X, то есть, для каждой f : X Y выполняется dom f = X
;
• X →
→
↦ Y – частичные сюръекции (сюрьективные функции), у
них область значений совпадает с Y, то есть, для каждой f :
X→
→
↦ Y выполняется ran f = Y ;
• X→
→ Y – сюръекции (сюръективные функции), у них множество значений совпадает с X и область значений совпадает с
Y, то есть, для каждой f : X →
→ Y выполняется dom f = X и
ran f = Y ;
• X
→ Y – биекции, то есть, всюду определенные взаимно однозначные сюръекции, то есть, для каждой f : X Y выполняется dom f = X и ran f = Y ;
agp1.fmsd 1.02.10
270
• X→
↦ ↦ Y – частичные конечные функции, у таких функций область определения – конечна (кстати и множество значений
тоже конечно, так как оно не может быть больше чем область
определения). Это подмножество всех частичных функций из
X в Y и, кроме того, подмножество F(X × Y)
• X
↦ ↦ Y – частичные конечные инъекции, то есть, конечные и
взаимно однозначные функции.
Формальные определения этих типов функций можно найти на
[20, стр.105] и [20, стр.112]. Обозначения стрелок для LaTex-а см.
[19, стр.40].
F.2.3.2 Реляционные операции над функциями
Некоторые операции над отношениями и функциями определяются в математической библиотеке языка Z (англ. matematical toolkit).
Формальные определения этих операций вместе с относящимися к
ним законами представлены в [20, стр.96-104]. Некоторые из этих
операций кратко перечисляются ниже:
• id A – отношение эквивалентности, в котором каждый элемент
области определения отображается в себя и только в себя в
области определения;
• Q o9 R – прямая композиция отношений (англ. forward relational
composition, обозначение см. [19, стр.39]), является бинарным
отношением у которого область определения является подмножеством области определения Q и множество значений является подмножеством множества значений R, при этом пара
(x, y) ∈ Q o9 R тогда и только тогда, когда найдется z для которого (x, z) ∈ Q и (z, y) ∈ R (’прямая композиция отношений’
часто называется просто ’композиция отношений’);
Замечание
agp1.fmsd 1.02.10
271
С этими композициями есть определенные трудности. Композиция (суперпозиция) функций (или отображений или
отношений) всегда являлось отношением между областью
определений и множеством значений ([42, стр.320]) то есть,
это множество пар. А по разделу ’Set comprehension revisited’
[15, стр.38] (в текущем документе это раздел F.2.2.10) это
должно быть множество троек (См. [20, стр.97]).
• Q∘R – обратная композиция отношений (англ. backward relational
composition), совпадает с композицией отношений, если операнды расположить в обратном порядке, то есть, Q ∘ R = R o9 Q
(прямая композиция отношений используется в спецификациях более широко по техническим причинам);
• ACR – ограничение области определения (англ. domain restriction),
результирующее отношение содержит только те пары из исходного отношения R, первый элемент которых принадлежит
A;
• A−
C R – антиограничение области определения (англ. domain
anti-restriction), для ограничения отношения используется дополнение ко множеству A;
• RBA – ограничение множества значений (англ. range restriction),
операция похожа на ограничение области определения, но для
ограничения используется множество значений;
• R−
B A – антиограничение множества значений (англ. range antirestriction), для ограничения множества значений используется дополнение к множеству A;
• R(| S |) – образ множества при заданном отношении (англ.
relational image), множество всех вторых элементов из пар,
принадлежащих отношению R, для которых первый элемент
пары принадлежит множеству S;
agp1.fmsd 1.02.10
272
• iter n R или более кратко Rn - степень (англ. relational iteration),
n раз выполняется суперпозиция отношения R с тем же отношением. Область определения и множество значений R должны входить в один тип (скажем, R ⊂ A × A), R0 == id A,
R1 = R, R2 = R o9 R, R3 = R o9 R o9 R и так далее;
• R – обратное отношение (англ. inverse relation), компоненты
кортежей этого множества располагаются в порядке противоположном порядку компонент кортежей исходного множества,
область определения и множество значений тоже меняются местами;
∼
• R* – рефлексивно – транзитивное замыкание (англ. reflexive –
transitive closure), объединение всех возможных степеней отношения R начиная с 0: R* = R0 ∪ R1 ∪ R2 ∪ . . . ;
• R+ – иррефлексивно – транзитивное замыкание (англ. irreflexive
– transitive closure), объединение всех возможных степеней отношения R начиная с 1: R+ = R* ∖ R0 ;
• Q ⊕ R = (dom R −
B A) ∪ R – переопределение (англ. overriding)
в результирующее множество пары подбираются следующим образом: если в Q и R есть пары с одинаковым первым элементом, то
берется пара из R, остальные пары берутся из Q.
Обозначения операций дла LaTex-а и текстового стиля спецификаций (.zsl) см. [19, стр.39].
F.2.4
Числа и последовательности
Числа и последовательности являются важными понятиями спецификаций. Они будут подробно описаны в этом разделе. Z включает
целые и натуральные числа (начинающиеся с 0) как множество вместе со обычным набором операций на них. Числа используются для
определения последовательностей.
agp1.fmsd 1.02.10
273
С помощью множеств можно описывать неупорядоченные наборы сущностей. Однако иногда требуется упорядочивать сущности
тем или иным способом. Так как упорядоченность очень важна в
спецификациях и, в частности, является первым шагом при уточнении спецификации, Z предоставляет понятие последовательности. В
последовательности сущности нумеруются при помощи натуральных
чисел. Набор операций и функций для работы с последовательностями тоже предоставляются в базовом инструментарии языка Z.
F.2.4.1 Числа
В спецификациях на языке Z часто используются целые числа:
Z = {. . . , −2, −1, 0, 1, 2, . . . }
и натуральные:
N = {n : Z|n ≥ 0} = {0, 1, 2, . . . }
F.2.4.2 Арифметика
В выражениях допустимы следующие операции на целых:
операция
сигнатура пример
сложение
+
2+2=4
вычитание
−
4−2=2
умножение
*
2*2=4
деление
div
5 div 2 = 2
остаток от деления mod
5 mod 2 = 1
обратный элемент −
−(−2) = 2
Для изменения порядка вычислений можно использовать круглые скобки. Например, 2 * (4 + 5) = 18. Так же доступны обычные
операции сравнения:
agp1.fmsd 1.02.10
274
операция
сигнатура пример
меньше
<
2 < 3, ¬ 3 < 2
меньше или равно ≤
2≤2
больше
>
a>b⇔b<a
больше или равно
≥
a≥b⇔b≤a
Есть операции выбора наибольшей и наименьшей величины в
непустом множестве чисел:
наибольшее число max{1, 2, 3} = 3
наименьшее число min{1, 2, 3} = 1
В случае применения операций к пустым множествам результат
будет не определен.
При необходимости не сложно добавлять нужные дополнительные операции. Например, функцию, которая возвращает модуль целого числа, можно определить при помощи аксиоматического описания следующим образом:
abs : Z → Z
∀n : Z ∙
n < 0 ⇒ abs n = −n ∧
n ≥ 0 ⇒ abs n = n
Заметьте, что ran abs == N.
Такое аксиоматическое описание доступно в любом месте спецификации. Так же существует обозначение для ненулевых натуральных чисел:
N1 = N ∖ {0} = {1, 2, 3, . . . }
Функция ’следующее число’ succ, после применение к натуральному число, возвращает число, следующее за ним:
succ = {0 ↦→ 1, 1 ↦→ 2, 2 ↦→ 3, . . . }
agp1.fmsd 1.02.10
275
Таким образом, ran succ = N1 . Она часто используется в спецификациях. Полезной бывает и обратная к ней функция ’предыдущее
число’ pred. При необходимости, она определяется следующим образом:
pred == succ∼
К этим функциям применимы следующие правила:
succ = N C ( + 1) = ( + 1) B N1
pred = N1 C ( + 1) = ( + 1) B N
succ o9 succ = N C ( + 2) = ( + 2) B N1 ∖ {1}
succ o9 pred = id N
pred o9 succ = id N1
F.2.4.3 Итерация
Иногда требуется выполнить композицию некоторого отношения
R : X ↔ X (то есть такого, у которого область определения и множество значений совпадают) n раз. Как уже выше отмечалось, это
записывается как Rn . Неформально, можно записать
Rn = R o9 R o9 · · · o9 R
n раз
Далее, взяв для примера функцию succ : N → N, можно выписать
следующие равенства:
succ0 = id N
– выполнение композиции отношений 0 раз просто дает отношение
эквивалентности;
succ1 = succ
agp1.fmsd 1.02.10
276
– выполнение композиции отношений один раз дает само отношение;
succ2 = succ o9 succ
– выполнение композиции отношения с собой;
succn = N C ( + n) = ( + n) B {i : N|i ≥ n}
– эти равенства выполняются для любого n : N;
succ−1 = succ∼
– обратное отношение является специальным случаем итерации. Как
было отмечено выше, обозначения R−1 и R∼ взаимозаменяемы, если
область определения и множество значений имеют одинаковый тип.
F.2.4.4 Диапазоны чисел
Диапазоны чисел (как множество чисел) между двумя целыми величинами a, b : Z обозначаются как
a . . b = {a, a + 1, a + 2, . . . , b − 2, b − 1, b}
или, более формально,
a . . b = {a ≤ n ≤ b}
Если a > b тогда a . . b = ∅. Кроме того, a . . a = {a}.
F.2.4.5 Мощность множества
Мощностью конечного множества (англ. cardinality) называется
число его элементов. Мощность множества s ∈ F T (множество всех
конечных подмножеств T) обозначается следующим образом # s. Таким образом, #∅ = 0, #{a} = 1, #{a, b} = 2, если a ̸= b и так далее.
Для диапазона чисел a . . b выполняется следующие равенства:
#a . . b = 1 + b − a если a ≤ b
agp1.fmsd 1.02.10
277
#a . . b = 0 если a > b
#a . . b = max{0, 1 + b − a}
Множество называется конечным, если существует чисел 1 . . . n
который можно биективно отобразить на него. При этом, число n
является мощностью или размером множества. Требуемое отображение можно построить при помощи подходящей конечной инъективной функции. Например, на множество a . . . b (где a ≤ b) можно
отобразить диапазон 1 . . . n при помощи функции f : N ↦ ↦ Z такой,
a−1
что f = succ B a . . . b. Множеством значений ran f является a . . . b,
а областью определения (dom f) есть a − (a − 1) . . . b − (a − 1) или
1 . . . 1 + b − a. То есть, как определено выше, мощностью a . . . b является число 1 + b − a.
F.2.4.6 Опять о типах
В языке Z целые числа Z рассматриваются как основной тип вместе со обычными арифметическими операциями. Натуральные числа
N ({0, 1, 2, . . . }) рассматриваются как подмножество целых. Таким
образом, натуральные числа не являются настоящим типом. Типом
переменной n : N является Z, а переменная n имеет дополнительное
ограничение и должна быть больше или равна 0. Подробности об
определении типов см. [20, Chapter 2].
Иногда R используется для обозначения вещественных чисел, хотя они не были определены в базовом инструментарии Z. Много приложений, в которых использовался язык Z, не требовали наличия
вещественных чисел. Вообще говоря, новые типы можно определять
точно так же как и числа.
Иногда требуется только факт существования некоторого множества, а не его конкретные величины. Такие множества (базовый тип,
англ. basic type, синоним – given set) вводятся следующим образом:
[Places] или несколько: [A, B, C]
agp1.fmsd 1.02.10
278
Далее, можно определить одно или несколько значений из этого типа:
[Places]
Oxford, Camridge : Places
Oxford ̸= Cambridge
Если важно быть уверенным, что Cambridge и Oxford это различные величины, то это требуется явно указать. В противном случае,
это может быть одна и таже величина с разными именами.
Новый тип можно определять явным перечислением (англ. data
type):
Methods ::= Z | VDM | RAISE | B
В этом случае тип Methods состоит из четырех различных величин. Доступна еще одна, более сложная форма, например, обозначение:
N ::= zero
| succ⟨⟨N⟩⟩
являет сокращенной формой такого определения:
[N]
zero : N
succ : N N
{zero} ∩ ran succ = ∅
{zero} ∪ ran succ = N
Такой тип называется свободным (англ. free type) Такие функции как succ будут называться конструкторами (англ. constructors).
Причем, такая сложная форма очень часто не нужна для большинства спецификаций. Подробно о свободных типах можно почитать
на [20, стр.82].
agp1.fmsd 1.02.10
279
F.2.4.7 Последовательности
Списки, массивы, файлы, последовательности являются различными именами для одного очень важного типа. Очень важной характеристикой величин этого типа является индексируемость их элементов. Обычно, в качестве индексов используется сплошной диапазон
натуральных чисел (например, 1 . . n).
Рассмотрим, как для любой пары (A, B) ∈ Places×Places множно
хранить наименьшую стоимость пути из A в B (то есть, отношение
(A, B) 𝜋 path). Например, её можно хранить в виде последовательности, причем ключ (A, B) будет упорядочен лексикографически для
ускорения доступа. Это будет примером для уточнения данных (англ. data refinement). Последовательность имеет первый, второй, третий и так далее элементы. Номера элементов последовательности в Z
обычно начинаются не с 0, а с 1. Если T является множеством, можно
определить множество конечных последовательностей из элементов
типа T следующим образом:
seq T == {s : N1 →
↦ ↦ T|dom s = 1 . . #s}
Это обозначение множества таких частичных функций из N в T, у
которых областью определения является конечный сегмент 1 . . из
N. Как уже определялось выше символ ′ . .′ задает интервал целых
чисел:
a . . b = {n : N|a ≤ n ≤ b}
Такие последовательности будут называться T- последовательностями. Нужно заметить, что они имеют конечную длину. Если s ∈ seq T,
то длина s будет обозначаться символом #s. Длина пустой последовательности s = ∅ равна 0 (#s = 0) и она обычно записывается
как ⟨⟩. Подобно пустому множеству, пустая последовательность тоже имеет тип. Непустые последовательности обозначаются
seq1 T == seq T ∖ {⟨⟩}
Последовательность можно рассматривать как функцию, значит к
ним применимо слово ’инъективная’. Для обозначения инъективных
agp1.fmsd 1.02.10
280
последовательностей (то есть, таких которые не содержат повторяющихся элементов из множества значений) используется обозначение
iseq T == seq T ∩ (N ↦ T)
Последовательность s из одного элемента (то есть, #s = 1) записывается как
⟨x⟩ = {1 ↦→ x} = s
Вообще говоря, сокращенная запись произвольной последовательности {1 ↦→ x1 , 2 ↦→ x2 , 3 ↦→ x3 , . . . , n ↦→ xn } выглядит следующим
образом
⟨x1 , x2 , . . . , xn ⟩
Далее, приводятся примеры использования этих обозначений:
⟨11, 29, 3, 7⟩ ∈ seq primes
Просто некоторые из простых чисел в случайном порядке.
⟨J, O, N, A, T, H, A, N⟩ ∈ seq Char
На этой строке символов нужно обратить внимание на отличие последовательностей от множеств, несмотря на похожий вид записи. В
примере есть два вхождения буквы ’N’ и они – различны. На деле,
это две различные пары 2 ↦→ N и 8 ↦→ N. Такое же рассуждение
относится и к двум вхождениям буквы ’A’. Длина (и мощность) у
этих двух примеров последовательностей – 4 и 7 соответственно.
Как отмечалось выше, в отличие от множеств, последовательности могут содержать повторяющиеся элементы:
⟨Emma⟩ =
̸ ⟨Emma, Emma, Emma⟩
Кроме этого, важен порядок элементов:
⟨Alice, Emma⟩ =
̸ ⟨Emma, Alice⟩
agp1.fmsd 1.02.10
281
F.2.4.8 Конкатенация
На последовательностях одного типа s, t ∈ seq T определена операция конкатенации (или присоединения одной последовательности
к концу другой): s a t это функция 1 . . (#s + #t) → T, элементы
которой задаются следующим образом:
{︃
s(j)
если 1 ≤ j ≤ #s
j ↦→
t(j − #s)
если #s < j ≤ (#s + #t)
Так же можно определить конкатенацию еще одним образом:
s a t = s ∪ ( − #s) o9 t
Существуют альтернативные определения конкатенации см. [20, стр.116].
⟨A⟩ a ⟨L, I, C, E⟩ = ⟨A, L⟩ a ⟨I, C, E⟩
И, вообще говоря, ⟨a, b, c, . . . ⟩ является сокращением для конкатенаций
⟨a⟩ a ⟨b⟩ a ⟨c⟩ a . . .
Законы для конкатенации
⟨⟩ a s = s a ⟨⟩ = s
r a (s a t) = (r a s) a t
(r a s = r a t) ⇒ s = t
F.2.4.9 Префикс
Отметим, что для двух последовательностей s, t ∈ seq T выражение s ⊆ t эквивалентно выражению ∃ t ∈ seq T ∙ s a r = t. То есть,
agp1.fmsd 1.02.10
282
применение операции включения ⊆ к паре последовательностей на
самом деле проверяет является ли левый операнд включения префиксом правого операнда. Например:
⟨m, a⟩ ⊆ ⟨m, a, n⟩
⟨⟩ ⊆ s пустая последовательность является префиксом пустой
s ⊆ s последовательность является своим собственным префиксом
Законы
Если одна последовательность является префиксом второй, а
вторая – префикс первой, то они одинаковы:
(s ⊆ t = t ⊆ s) ⇒ s = t
Если последовательность является префиксом второй, а она,
в свою очередь, префиксом третьей, то первая последовательность тоже является префиксом третьей:
(r ⊆ s ∧ s ⊆ t) ⇒ r ⊆ t
Если две последовательности являются префиксом третьей, но
либо первая является префиксом второй, либо вторая является
префиксом первой. Заметьте, что этот же закон применим ко
множествам:
(r ⊆ t ∧ s ⊆ t) ⇒ (r ⊆ s ∨ s ⊆ r)
В базовый инструментарий языка Z входит отношение s prefix t, см.
[20, стр.117].
agp1.fmsd 1.02.10
283
F.2.4.10 Остальные операции на последовательностях
В спецификациях часто возникает необходимость извлекать первый или последний элемент последовательности или остаток последовательности без первого или последнего элемента. Для выполнения этих четырех действий существует четыре функции. Если s ∈
seq T и s ̸= ⟨⟩ (то есть, s ∈ seq1 T):
head s = s(1) первый элемент последовательности
last s = s(#s) последний элемент последовательности
tail s = succ o9 ({1}−
Cs) последовательность без первого элемента
front s ={#s}−
Cs последовательность без последнего элемента
Замечание
Результат применения этих операций к пустой последовательности – не определен.
Возьмем для примера последовательность ⟨c, o, d, e⟩ (другими словами это {1 ↦→ c, 2 ↦→ o, 3 ↦→ d, 4 ↦→ e} ), тогда:
head s = c
last s = e
tail s ={0 ↦→ 1, 1 ↦→ 2, 2 ↦→ 3, 3 ↦→ 4, . . . }o9{2 ↦→ o, 3 ↦→ d, 4 ↦→ e}
={1 ↦→ o, 2 ↦→ d, 3 ↦→ e}= ⟨o, d, e⟩
front s ={4}−
C{1 ↦→ c, 2 ↦→ o, 3 ↦→ d, 4 ↦→ e}
={1 ↦→ c, 2 ↦→ o, 3 ↦→ d}= ⟨c, o, d⟩
agp1.fmsd 1.02.10
284
Если потребуется для некоторого приложения можно использовать более общие версии операций front и tail. У этих операций есть
параметр, которым можно задавать длину возвращаемых последовательностей. Операции создаются при помощи шаблонов языка Z
(англ. generic construction):
[T]
for , after : (seq T) × N → (seq T)
∀ s : seq T; n : N ∙
s for n = (1 . . n) C s ∧
s after n = ({0} −
C succn ) o9 s
Замечание 1
Совершенно непонятно, как добиться, что бы текст такого шаблона операции был совместим с утилитой ZTC. Именно эта, обсуждаемая схема, редактировалась после обработки ZTC и утилита выдает на ней синтаксические ошибки. Примеры операций в библиотеках инструментальных средств существуют. Но,
глядя на них, не получается записать свою операцию, все равно, в текстовом, рамочном стиле или стиле LaTex-а. Таким образом, писать спецификацию с использованием операций, как
бы можно, но идея о использовании утилиты ZTC для проверки таких спецификаций становится нереализованной. При
функциональной форме этих операций (for, after) компиляция
файлов создает меньше проблем.
Замечание 2
Утилита ZTC позволяет создавать шаблоны операций для ограниченного набора символов. К таким символам относятся, например, mapsto, =, .., subset, oplus, dres, +, ++, %, %%. Для
произвольных имен, например, для рассмотренных выше for и
after создать шаблон операции не удается.
Например, если файл рассматривать как последовательность байт,
то эти две функции были бы полезны для извлечения частей файла.
agp1.fmsd 1.02.10
285
Вспомним, что для s ∈ seq1 T:
front s = s for (# − 1)
tail s = s after 1
Некоторые равенства для этих операций:
s for 0 = ⟨⟩
s for #s = s
s after 0 = s
s after #s = ⟨⟩
F.2.4.11 Обратный порядок последовательности
Если s ∈ seq T, то rev s дает последовательность элементов, расположенных в порядке обратном к порядку элементов s. Например
rev⟨d, o, g⟩ = ⟨g, o, d⟩.
Некоторые равенства операции:
rev ⟨⟩ = ⟨⟩
rev ⟨x⟩ = ⟨x⟩
rev(rev s) = s
rev(s a t) = (rev t) a (rev s)
Например:
rev(⟨a, b⟩ a ⟨c, d⟩) = ⟨d, c⟩ a ⟨b, a⟩
agp1.fmsd 1.02.10
286
F.2.4.12 Распределенная форма операций
Распределенная форма операций == distributed operations. Иногда бывает полезной конкатенация не двух, а нескольких последовательностей:
a/⟨⟩ = ⟨⟩
a/⟨a, b, . . . , n⟩ = a a b a · · · a n
Более формально, функция a/ : seq(seq T) → seq T удовлетворяет
правилу
a/(⟨a⟩ a s) = ⟨a⟩ a (a/s)
и
a/(s a ⟨a⟩) = (a/s) a ⟨a⟩
Формальное определение операции см. [20, стр.121].
Для остальных операций на последовательностях тоже можно
определить распределенную форму, если она понадобится для конкретной цели. Рассмотрим, например, результаты обновления базы
данных последовательностью частичных функций. Можно определить распределенный оператор обновления (англ. overriding operator)
в терминах обычного (dyadic) оператора обновления, чтобы обобщить обновление отношения. Неформально:
⊕/⟨a, b, . . . , n⟩ = a ⊕ b ⊕ · · · ⊕ n
F.2.4.13
Разделимость и покрытие
Замечание
Этот раздел в оригинале называется ’Disjointness and partitioning’.
Пока ничего лучше не придумал.
agp1.fmsd 1.02.10
287
Последовательность множеств считается разделенной (англ. disjoint)
если в ней не существуют пересекающиеся множества. Формально:
∀ S : seq P T ∙ disjoint S ⇔ (∀ i, j : dom S|i ̸= j ∙ (Si) ∩ (Sj) = ∅)
Пустая последовательность и любая одно элементная последовательность являются разделенными, так как каждая из них не содержит двух элементов, что бы попробовать их пересекать. Таким
образом, disjoint ⟨⟩ и disjoint ⟨a⟩ всегда выполняются.
Для двух элементной последовательности disjoint S означает S1 ∩
S2 = ∅.
Для трех элементной последовательности disjoint S означает
S1 ∩ S2 = ∅ ∧ S2 ∩ S3 = ∅ ∧ S3 ∩ S1 = ∅
и так далее.
Возможно расширить эту идею что бы обсудить обобщенное объединение всех множеств из последовательности. Тогда говорят, что
такая последовательность является разбиением множества (которое
получается в результате объединения всех множеств последовательности). Формально:
⋃︀
∀ S : seq P T; P : P T ∙ S partition P ⇔ (disjoint S ∧ P = {i : dom S ∙ Si })
Разделимость и покрытие можно обобщить на любое индексированное множество. То есть, подставить в определение
S:I→
↦ P T вместо seq S : P T
.
F.2.4.14 Порядок
Если это потребуется для некоторых приложений, то математическая библиотека языка Z может быть расширена. Например, вполне
agp1.fmsd 1.02.10
288
может пригодиться частичный порядок (рефлексивное, антисимметричное и транзитивное отношение, некоторые элементы нельзя сравнивать):
partial order[X] =={ R : X ↔ X|(∀ x, y, z : X∙
xRx∧
(x R y ∧ y R x) ⇒ x = y ∧
(x R y ∧ y R z) ⇒ x R z)}
Далее, при помощи частичного порядка можно определить отношение вполне упорядоченности (англ. total order). В этом отношении
сравнимыми оказывается все элементы множества X:
partial order[X] ==
{ R : partial order[X] | (∀ x, y : X∙
x R y ∨ y R x)}
F.2.4.15 Заключение
В этом разделе вкратце обсуждались числа и их использование
для определения понятия последовательности, важную для большого числа спецификаций структуру данных. Так же была рассмотрены способы языка Z для использования последовательностей.
Введение в математическую запись языка теперь закончено. Реже
используемые возможности Z (такие как bags) не рассматривались
в текущем документе. Их можно посмотреть, начиная со страницы
agp1.fmsd 1.02.10
289
124 [20]. После уверенного освоения спецификаций Z, имеет смысл
исследовать оставшиеся возможности языка.
Математика в спецификациях очень полезна для маленьких примеров, но становится явно недостаточной при переходе к более реалистичным задачам. Для преодоления возрастающих трудностей язык
Z использует понятие схема (англ. schema), которое позволяет писать
хорошо структурированные спецификации из небольших модулей. В
разделе F.2.4.2 можно посмотреть пример схемы для определения
функции модуля. В следующем разделе можно будет увидеть, как
такие схемы объединяются, чтобы создать большие спецификации.
F.2.5
Схемы
Для структурирования спецификаций языка Z используется понятие, называемое схема. Оно считается полезным, для того чтобы
записывать спецификации любого размера. Далее следует пример
схемы:
Book
author : People
title : seq Char
readership : P People
rating : People →
↦ 0 . . 10
readership = dom rating
Эта схема определяет одного автора для книги – author, заголовок книги – title, читателей книги – readership (множество людей в схеме задается символом P в декларации), кроме того, определен рейтинг книги – частичная функция rating (множество значений
функции: число от 0 до 10). При необходимости, в нижней половине
схемы могут быть добавлены дополнительные ограничения целостности (англ. constraint) в виде предикатов. В представленной схеме
записано, что область определения функции rating совпадает с множеством читателей.
agp1.fmsd 1.02.10
290
Верхняя часть схемы Book определяет несколько переменных с
их ограничениями, из которых можно получить сведения о типе переменных. Например, seq Char является подмножеством частичных
конечных функций N →
↦ ↦ Char (определение seq см. [20, стр.155]), которое в свою очередь является подмножеством отношения Z ↔ Char
или, что тоже самое, P(Z×Char) (см. [20, стр.95]). Далее, выражение
0..10 подразумевает подмножество целых чисел с дополнительным
ограничением: значения меняются от 0 до 10.
Замечание
Определение типа Char находится во второй математической
библиотеке утилиты ZTC: math2.zbx (см. раздел F.1.1 ).
Рассмотренную схему можно переписать в несколько другой форме:
Book
author : People
title : P(Z × Char)
readership : P People
rating : P(People × Z)
title ∈ seq Char
rating ∈ People →
↦ 0 . . 10
readership = dom rating
Нужно отметить, что все предикаты в нижней части схемы считаются связаны логическим И по умолчанию. Определение переменных во второй схеме использует наиболее общие типы для переменных, в отличие от первой. Именно эти общие типы используются в
утилитах проверки правописания (англ. grammar checker) Кроме того, такие типы должны облегчать понимание спецификации во время
чтения.
Схемы, в основном, используются для описания состояния и операций при математическом моделировании проектируемых систем.
Например, пусть существует схема с названием StateSpace:
agp1.fmsd 1.02.10
де:
291
Если хочется её уменьшить, можно записывать в следующем ви-
Или даже в виде одной строки, например:
StateSpace =
̂︀ [x1 : S1 ; . . . ; xn : Sn |Inv(x1 , . . . , xn )]
Эта схема описывает пространство состояний приложения (англ. state space) в котором x1 , . . . , xn – это переменные состояния, а
S1 , . . . , Sn – выражения из которых можно определить тип соответствующей переменной.
Замечание
Следующий не совсем понятный текст оставлен до лучших времен. Z types are sets – x1 , . . . , xn should not occur free in S1 , . . . , Sn
or if they do, they refer instead to other occurrence of these variables
already in scope (e.g., globally defined variables).
agp1.fmsd 1.02.10
292
Inv(x1 , . . . , xn ) является инвариантом, который некоторым образом
связывает переменные для всех возможных состояний системы на
протяжении её работы.
Нужно отметить, что переменные состояния в схеме считаются
неупорядоченными. Изменение порядка определения переменных не
меняет схему, и этими переменными можно пользоваться в выражениях только в нижней части схемы. Таким образом все зависимости в
системе должны быть определены в нижней части. Обычная ошибка
начинающих пользователей языка Z приводит к попыткам описания
зависимостей в верхней, декларативной части.
F.2.5.1 Пример спецификации
В первой главе [20] излагается известный пример системы для записывания дней рождений: ’Книга дней рождений’. Она начинается
с введения следующих типов (именованых множеств):
[NAME, DATE]
Пространство состояний приложения задается следующей схемой:
BirthdayBook
known : P NAME
birthday : NAME →
↦ DATE
known = dom birthday
Переменными состояния (англ. state variables) в этой схеме оказываются known (имена знакомых) и birthday (уникальные даты,
которые ассоциированы с каждым именем знакомого). Инвариантным свойством этой схемы является следующая формула:
known = dom birthday
то есть, для каждого имени существует своя дата дня рождения.
agp1.fmsd 1.02.10
293
В языке существуют специальные декорации идентификаторов
переменных, чтобы подсказать читателю правильную интерпретацию этих идентификаторов. Переменная без декорации представляет
текущее состояние (состояние ПЕРЕД). Переменная, за которой следует символ (′ ) представляет следующее состояние (состояние ПОСЛЕ). Переменная с последующим символом (?) представляет входную переменную схемы. Переменная с последующим символом (!) –
выходную. Обычная схема операций, описывающаяя изменение состояния, подобна следующей (operation schema):
В этой схеме:
• переменные i1 ?, . . . , im ? являются входными;
• o1 !, . . . , op ! – выходными;
• выражение Pre(i1 ?, . . . , im ?, x1 , . . . , xn ) является предусловием;
• изменение состояния от (x1 , . . . , xn ) (x′1 , . . . , x′n ) задается выражением
Op(i1 ?, . . . , im ?, x1 , . . . , xn , x′1 , . . . , x′n , o1 !, . . . , op !)
.
agp1.fmsd 1.02.10
294
Нужно отметить, что если нет ограничений целостности для переменных текущего и следующего состояния, то они могут принимать
любые значения. То есть, в отличие от большинства языков программирования, если явно не задана зависимость переменных следующего состояния от переменных текущего состояния то значит,
что она отсутствует. Таким образом, требуется явно задать предикат
x′1 = x1 ifx1 , если требуется гарантировать одинаковое значение в обеих переменных. Это соглашение может оказаться непривычным для
некоторых программистов, но является крайне полезным в спецификациях. Вскоре будет представлено соглашение о способе записи, которое утверждает неизменность нескольких переменных состояния.
Следующий пример схемы операций содержит добавление дня
рождения к книге дней рождений:
AddBirthday
known : P NAME
birthday : NAME →
↦ DATE
′
known : P NAME
birthday′ : NAME →
↦ DATE
name? : NAME
date? : DATE
name? ̸∈ known
known = dom birthday
known′ = dom birthday′
birthday′ = birthday ∪ {name? ↦→ date?}
Полное состояние вместе с его инвариантами повторяется для переменных текущего (без декорации) и следующего (с декорацией ′)
состояний. Для удобства одна схема может быть ’включена’ в другую
схему, таким образом, эта же спецификация может быть записана
в более лаконичной манере. При этом шесть строк схемы, которая
приведена выше, заменяются одной строкой подключения (см. [20,
стр.4]):
agp1.fmsd 1.02.10
295
AddBirthday
ΔBirthdayBook
name? : NAME
date? : DATE
name? ̸∈ known
birthday′ = birthday ∪ {name? ↦→ date?}
Предусловием для этого примера является выражение name? ̸∈
known. А, собственно, сама операция в спецификации задается предикатом
birthday′ = birthday∪{name? ↦→ date?}
который описывает состояние после выполнения операции AddBirthday.
Новая значение (birthday′ ) переменной состояния birthday является
birthday∪{name? ↦→ date?}
.
В схемах языка Z можно указывать использование другой схемы
при помощи символов: Δ (дельта) – для описания операций, которые
меняют состояние и Ξ (хи) – для описания операций, которые не
меняют состояние.
Пусть дана схема:
тогда схема:
agp1.fmsd 1.02.10
296
является сокращением полной схемы:
Такое использование одной схемы (ΔStateSpace) внутри другой
называется подключением схемы (англ. schema inclusion), это полезная техника Z используется для структурирования спецификаций.
При этом, все компоненты состояния и связанные с ними предикаты добавляются к подключающей схеме. Это может быть полезно
для многократного использования компонент спецификации в других проектах. Использование подключений схем позволяет детальное описание необходимых компонент скрывать в соответствующих
местах спецификации, где они могут быть определены и детально
описаны заранее.
В качестве конкретного примера подключения схемы операцию
AddBirthday можно специфицировать используя ΔBirthdayBook. Вот
такая, более короткая версия еще раз:
agp1.fmsd 1.02.10
297
Некоторым операциям требуется доступ к состоянию другой схемы, но они её не меняют. Например:
Строго говоря, Inv(x′1 , . . . , x′n ) тоже надо включать в качестве предиката, но это излишне, в связи со вторым и третьим предикатом в
приведенной схеме.
Примером схемы с такой операцией является FindBirthday, эта
операция ищет день рождения для заданного имени:
agp1.fmsd 1.02.10
298
Предусловием является предикат name? ∈ known и, собственно,
операция описана предикатом date! = birthday(name?).
Ξ-подключение используют, чтобы компактно описывать такие
операции. Оно похоже на Δ – подключение, но в подключающую
схему добавляются ограничения на компоненты состояния, которые
не меняют их значения.
Рассмотрим схему пространства состояний:
Тогда следующая схема операции:
agp1.fmsd 1.02.10
299
является сокращенной версией полного варианта:
Например, схема FindBirthday может быть записана с использованием ΞBirthdayBook следующим образом:
FindBirthday
ΞBirthdayBook, name? : NAME
date! : DATE
name? ∈ known
date! = birthday(name?)
Она просто является сокращенной версией для предыдущей схемы FindBirthday.
F.2.5.2 Операторы над схемами
Существует несколько операторов над схемами, соответствующих
( см. [20, стр.74]) логическим связкам, таким как ¬ , ∨, ∧, ⇒, ⇔, и,
кроме них, соответствующих кванторам ∀, ∃, ∃1 . Для использования
операторов схемы сначала нормализуются. В случае операторов с
двумя операндами, схемы не должны иметь конфликтующих объявлений. В случае отрицания схемы – нормализация особенно особенно
важна, чтобы убедиться в отрицании каждого скрытого предиката –
agp1.fmsd 1.02.10
300
ограничения целостности в объявлении. В случае операторов с двумя операндами – объявления из обеих схем соединяются в схеме –
результате (нужно помнить, что порядок объявлений – не важен),
предикаты тоже соединяются в зависимости от используемого оператора. Cм. [20, 32-34 стр.] для дополнительных объяснений и примеров.
Есть возможность использовать схемы в объявлениях в качестве
типа (например, state : StateSpace). Если такое объявление есть в области видимости, то есть возможность доступа к компонентам схемы.
Например, state.x1 возвращает компонент x1 и так далее.
Полезным так же являются кортежи схем. Кортеж схемы похож
на упорядоченный кортеж, но считается неупорядоченным, с именованными компонентами. Например, для схемы StateSpace запись
𝜃StateSpace обозначает требуемый кортеж схемы. В нем содержатся
все именованные компоненты x1 , . . . , xn . В качестве примера определим следующим образом схему, удовлетворяющую соглашению Ξ:
′
ΞStateSpace=[ΔStateSpace|𝜃StateSpace
^
= 𝜃StateSpace]
Несколько компонент схемы могут быть спрятаны (англ. schema
hiding, existentially quantified). Например, StateSpace ∖ (x1 , x2 ) является следующим утверждением: ∃ x1 : S1 ; x2 : S2 ∙ StateSpace.
Существует обратная операция – проектирование схемы (англ.
schema projection). Например, пусть ProjectState=[x
^ 1 : S 1 ; x2 : S 2 ]
тогда выражение StateSpace ProjectState наоборот, прячет все компоненты схемы StateSpace кроме x1 и x2 .
Кроме того, компоненты схемы могут быть переименованы (англ. schema renaming) Например, StateSpace[y1 /x1 , y2 /x2 ] возвращает
новую схему, в которой компонента x1 заменена компонентой y1 , x2 –
y2 . Это бывает полезно, если в схемах спецификации по каким либо
причинам возникла многократное определение компонент.
Существует оператор для извлечения предусловий из схемы. Выражение preOperation извлекает? (existentially quantifies) все следующие состояния (состояния ПОСЛЕ) и выходные компоненты. То
agp1.fmsd 1.02.10
301
есть,
∃ x′1 : S1 ; . . . ; x′n : Sn ; o1 ! : T1 ; . . . ; op ! : Tp ∙ Operation
Еще один оператор на схемах называется последовательная композиция (англ. sequential composition). Определим две операции Operation1
и Operation2:
и
тогда выражение Operation1 o9 Operation2 является следующей
схемой:
agp1.fmsd 1.02.10
302
Все переменные z′1 , . . . , z′n из следующего состояния операции Operation1
которые соответствуют переменным z1 , . . . , zn текущего состояния
операции Operation2 объединяются и existentially quantified в качестве нового промежуточного состояния z′′1 , . . . , z′′n . Остальные компоненты, то есть, x1 , . . . , xp операции Operation1 и y1 , . . . , yq операции Operation2 (включая любые входные и выходные переменные)
оказываются не соответствующими друг другу в этом смысле. Если
какие-то из них соответствуют друг другу в смысле совместимости
типа, то они объединяются так, как это происходило в других операторах вроде конъюнкции.
Таким образом, схема AddBithday o9 FindBirthday должна трактоваться как следующая:
Существует еще один оператор над схемами – schema piping (≫),
при котором, в соответствие друг другу ставятся не компоненты следующего и текущего состояния, а выход первой схемы и вход второй
схемы,
agp1.fmsd 1.02.10
303
F.2.5.3 Свойства
Примером простого свойства, которое может понадобиться доказать является следующее:
AddThenFindBirthday ⊢ date! = date?
То есть, если выполнить операцию AddBirthday (с именем и днем
рождения date?), а затем, дать такое же имя на вход операции FindBirthday,
то выход (день рождения date!) последней будет совпадать со входом
первой (день рождения date?). Будучи доказанными, такие свойства
повышают уровень уверенности в том, что спецификация корректна,
так как это соответствует интуитивному ожиданию читателя. Если
данное свойство не может быть доказано, то это может указывать
на недостаток требующий исправления. Причем такой недостаток
будет обнаружен задолго до начала реализации специфицируемой
системы в языке программирования. В случае неформального проектирования системы, такие ошибки будут обнаруживаться на более
поздних стадиях работы: таких как кодирование, тестирование или
даже после сдачи системы в эксплуатацию. Что повышает стоимость
исправления ошибки.
Нужно отметить, что язык Z как его определил Spivay в [20], не
содержит возможностей для записывания теорем. Для этих целей
можно использовать соглашение ⊢ p, где p – некоторый предикат. И
выражение d ⊢ p можно использовать для квантора всеобщности в
декларации d.
F.2.6
Привычные типы, не встроенные в язык Z
Логический тип, вещественные числа, символы, строчки – отсутствуют в языке Z.
• Замечания по логическому типу см. [17, Z and Boolean types,
108 page ] и [36, Z и логический тип].
• Замечания по вещественным числам см. F.1.1.3 и [37].
agp1.fmsd 1.02.10
304
• Символы вводятся в библиотеке math1 как базовый тип (англ.
base type) CHAR. Строки как последовательности символов:
[ Char ]
String == seq Char
|
|
|
|
ascii_of : Char +-> N;
unicode_of : Char +-> N;
ascii_char : N +-> Char;
unicode_char : N +-> Char
Предоставляются функции для конвертации символов в/из коды/кодов.
F.2.7
Императивный стиль
Переменные языка Z см. [20, стр.12] (схема BirthdayBook1 – тут описаны три переменные), [30, Уточнение состояние Книга Дней Рождения]. Это аналоги полей будущего реализованного класса.
Аналог присвоения см. [20, стр.13] (схема AddBirthday1 – тут
описано старое (без штриха) и новое состояние (со штрихом) переменных, символ Δ перед именем используемой схемы сообщает, что
состояние переменных в используемой схемы будет изменено).
В качестве аналогов циклов можно использовать либо использование рекурсивных функций (см.[38, стр.12]), либо квантор всеобщности (см.[38, стр.14], [36, Б.2 Факториал] ). Как видно по спецификации итератора, использование рекурсивных функций в нетривиальных случаях влечет переусложненную и малопонятную спецификацию. В случае квантора всеобщности спецификация становится
короче, но достаточно далека от кода. Наличие в языке конструкций
для циклов (см. язык RSL [12, Iterative Expressions], [56, стр.47]) позволило бы дополнительно приблизить спецификацию к коду.
agp1.fmsd 1.02.10
F.2.8
305
Выводы
В высшей степени краткий обзор языка Z закончен. Более полное
изучение можно продолжить, читая монографию [20].
F.3
Краткий справочник по символам языка Z
В разделе собраны часто используемые символы тестового стиля
(ASCII версия) спецификаций Z (со ссылкой на страницу в [20], где
определяется этот символ), которые утилита ZTC преобразует в символы стиля LaTex-а (см. [19]). Указатель символов языка см. [20,
стр.153]. Краткое введение в язык Z, которое представляет собой перевод из монографии [15, гл.3] находится в разделе F.2.
Таблица F.9 – Символы для логики
символ LaTex-a
false
true
¬
∧
∨
⇒
⇔
∀
∃
∃1
∙
ASCII версия
false
true
not
and
or
implies
iff
forall
exists
exists1
@
что значит
нет
да
отрицание
логическое И
логическое ИЛИ
влечет
эквивалентность
квантор всеобщности
квантор существования
квантор уникальности
элемент предиката
[80]
F.2.1.1
F.2.1.1
F.2.1.1
F.2.1.1
F.2.1.1
F.2.1.1
F.2.1.1
F.2.1.2
F.2.1.2
F.2.1.2
F.2.1.2
[19]
37
37
37
37
37
37
37
37
37
37
37
[20]
29
29
69, 75
69, 75
69, 75
69, 75
69, 75
70, 76
70, 76
70, 76
70, 76
agp1.fmsd 1.02.10
306
Таблица F.10 – Символы для прямого произведения
символ LaTex-a
×
↦
→
first
second
(...)
ASCII версия
&
mapsto
first
second
(...)
что значит
прямое произведение
соответствует
первый элемент пары
второй элемент пары
кортеж
[80]
F.2.2.9
F.2.2.12
F.2.2.9
F.2.2.9
F.2.2.9
[19]
38
39
39
39
39
Таблица F.11 – Символы для выражений
символ LaTex-a
𝜆
𝜇
if
then
else
let
ASCII версия
lambda
mu
if
then
else
let
let
let
что значит
[80]
лямбда-выражение
мю-выражение
пусть - локальное
определение
предикат
[19]
37
37
38
38
38
F.1.2.2 38
[20]
58
58
64
64
64
59
F.1.2.2 37
71
Пример с использованием пар, фразы let и последовательностей
можно посмотреть в разделе [81, Алгоритм итератора Пеано].
[20]
56
95
93
93
93
agp1.fmsd 1.02.10
307
Таблица F.12 – Символы для функций
символ
LaTex-a
→
→
↦
↦
→
→
→
→
↦
→
→
↦↦
↦↦
ASCII
версия
fun
pfun
inj
pinj
surj
psurj
bij
ffun
finj
что значит
всюду определенная функция
частичная функция
всюду определенная инъекция
частичная инъекция
всюду определенная сюръекция
частичная сюръекция
биекция
конечная функция
конечная частичная инъекция
[80]
[19] [20]
F.2.3.1
F.2.3.1
F.2.3.1
F.2.3.1
F.2.3.1
F.2.3.1
F.2.3.1
F.2.3.1
F.2.3.1
40
40
40
40
40
40
40
40
40
105
105
105
105
105
105
105
112
112
Пример с использованием неявного описания функций можно посмотреть в разделе [81, Спецификация арифметики Пеано].
Таблица F.13 – Символы для последовательностей
символ LaTex-a
seq
seq1
#
iseq
ASCII версия
seq
seq1
#
iseq
⟨...⟩
head
tail
last
front
a
<<...>>
head
tail
last
front
^
rev
rev
что значит
последовательность
не пустая
длина последо-ности
последовательность из
уникальных элементов
скобки
первый
остаток без первого
последний
остаток без последнего
конкатенация
обратная
[80]
F.2.4.7
F.2.4.7
F.2.4.7
F.2.4.7
[19]
41
41
41
41
[20]
115
115
115
115
F.2.4.7
F.2.4.10
F.2.4.10
F.2.4.10
F.2.4.10
F.2.4.8
F.2.4.11
41
41
41
41
41
41
41
115
117
117
117
117
116
116
agp1.fmsd 1.02.10
308
Таблица F.14 – Символы для cхем
символ
LaTex-a
::=
Δ
Ξ
=
̂︀
ASCII
версия
::=
Delta
Xi
=^=
что значит
[80]
[19]
[20]
определение свободного типа
дельта подкл.схему менять
хи подкл.схему не менять
определение схемы
F.2.4.6
F.2.5.1
F.2.5.1
стр.291
36
36
36
5,35
82
131
131
49
Таблица F.15 – Символы для множеств
символ LaTex-a
∅
{a}
∙
...
̸
=
∈
̸
∈
⊂
⊆
∪
∩
∖
⋃︀
⋂︀
P
P1
F
F1
#
P−
ASCII версия
{}
{a}
@
...
/=
in
notin
subset
subseteq
setunion
setint
setminus
Union
Intersection
P
P1
F
F1
#
что значит
пустое множество
скобки для множества
сокр.опр.множества
и так далее
не равно
принадлежит
не принадлежит
строго включается
включается
объединение
пересечение
разность
объединение
пересечение
булеан
булеан без пустого
все конечные
все конечные
без пустого
мощность множества
дополнение
[80]
F.2.2.2
F.2.2.2
F.2.2.10
F.2.2.2
F.2.2.2
F.2.2.2
F.2.2.2
F.2.2.3
F.2.2.3
F.2.2.3
F.2.2.3
F.2.2.3
F.2.2.4
F.2.2.4
F.2.2.11
F.2.2.11
F.2.2.11
F.2.2.11
F.2.4.5
F.2.2.3
[19]
38
38
39
38
38
38
38
38
38
38
38
38
38
39
38
38
38
38
38
41
Для сокращенного определения множества, кроме символа @, еще
[20]
90
55
57
55
89
68
89
90
90
91
91
91
92
92
56
90
111
111
90
111
agp1.fmsd 1.02.10
309
используется вертикальная черта, за которой следует предикат. Если
используются оба символа, то идет элементы исходного множества,
затем – вертикальная черта, затем – предикат, затем выражения над
элементами исходного множества, которые удовлетворяют предикату.
Таблица F.16 – Символы для отношений
символ
LaTex-a
↔
↦
→
dom
ran
id
o
9
∘
C
B
−
C
−
B
⊕
R(| S |)
R∼
R*
R+
Rk
ASCII
версия
rel
mapsto
dom
ran
id
comp
backcomp
dres
что значит
отношение
пара
область определения
множество значений
отношение эквивалентности
прямая композиция
обратная композиция
ограничение области
определения
rres
ограничение множества
значений
dsub
антиограничение области
определения
rsub
антиограничение множества
значений
oplus
переопределение
R(| S|)
образ множества
R invertion обратное отношение
R ~
R rtclosure рефлексивно транзитивное
R ^ *
замыкание
R tclosure иррефлексивно транзитивное
R ^ +
замыкание
R^(k)
степень
[80]
[19] [20]
F.2.2.12
F.2.2.12
F.2.2.12
F.2.2.12
F.2.3.2
F.2.3.2
F.2.3.2
F.2.3.2
39
39
39
39
39
39
39
39
95
95
96
96
97
97
97
98
F.2.3.2
39
98
F.2.3.2
39
99
F.2.3.2
39
99
F.2.3.2 39
F.2.3.2 39
F.2.2.12 39
102
101
100
F.2.3.2
39
103
F.2.3.2
39
103
F.2.3.2
39
110
agp1.fmsd 1.02.10
310
Таблица F.17 – Символы для чисел
символ LaTex-a
Z
N
N1
..
̸
=
div
mod
≤
≥
succ
pred
min
max
F.3.1
ASCII версия
Z
N
N1
upto
/=
div
mod
<=
>=
succ
pred
min
max
что значит
целые числа
натуральные числа + 0
натуральные числа
диапазон
не равно
деление
остаток от делениЯ
меньше или равно
больше или равно
следующее
предыдущее
наименьшее
наибольшее
[80]
F.2.4.1
F.2.4.1
F.2.4.2
F.2.4.4
F.2.4.2
F.2.4.2
F.2.4.2
F.2.4.2
F.2.4.2
F.2.4.2
F.2.4.2
F.2.4.2
F.2.4.2
[19]
40
40
40
40
40
40
40
40
40
40
[20]
108
108
109
109
41
41
113
113
Структура спецификации
Спецификация состоит из следующих разделов: начального раздела
zed, раздела аксиом, шаблонов, схем и синтаксиса.
F.3.1.1 Раздел Zed
В этом разделе определяют имена базовых типов (given set), синонимов, определяются схемы, и предикаты, а так же свободные типы и
базовые типы (см. F.2.4.6, [17, Defining new types, 70 page ], [36, Определение новых типов], F.3.1.4). Командой \also раздел делится на
параграфы. Если рассматривать спецификацию в стиле LaTex-a.
The zed environment is used to define other paragraphs in Z,
including given sets, schema definitions, equivalence definitions,
and predicates. Short free type definitions can also be included
in the zed environment. A zed environment may contain several
108
108
108
108
109
agp1.fmsd 1.02.10
311
paragraphs. The paragraphs in a zed environment must be separated
by the \also command.
Пример из [17, стр.49]:
---- File:./src/intro/text.zsl
specification
[ CHAR ]
%
базовый тип
TEXT == seq CHAR
%
синоним для посл-ти символов
end specification
---- End Of File:./src/intro/text.zsl
CHAR – это обозначение базового типа для спецификации (given set),
TEXT – обозначение эквивалентное для последовательности символов seq CHAR, обычно более короткое. Аналог макросов в языке
Си. Пустые строчки – обязательны. Утилитой ZTC компилируется в
следующий файл:
---- File:./src/intro/text.zed
\begin{spec}
\begin{zed}
[ CHAR ]
\also
TEXT == \seq CHAR
\end{zed}
\end{spec}
---- End Of File:./src/intro/text.zed
В построенном документе выглядит следующим образом:
[CHAR]
TEXT == seq CHAR
agp1.fmsd 1.02.10
312
F.3.1.2 Комментарии
Комментарии – однострочные и начинаются с символа процент %.
F.3.1.3 Аксиомы
Оформление раздела аксиом в текстовом стиле (в разделе задается
максимальное значение для целых):
---- File:./src/intro/axdef.zsl
specification
global
MaxSize : N
axiom
MaxSize <= 65535
end axiom
end specification
---- End Of File:./src/intro/axdef.zsl
Этот же пример в стиле LaTex-а:
---- File:./src/intro/axdef.zed
\begin{spec}
\begin{axdef}
MaxSize : \nat
\where
MaxSize \leq 65535
\end{axdef}
\end{spec}
---- End Of File:./src/intro/axdef.zed
Вид раздела аксиом после включения в документ LaTex-а:
MaxSize : N
MaxSize ≤ 65535
Имена, которые объявляются в разделе аксиом, считаются константами. Константы доступны глобально, на протяжении всей спецификации ([17, стр.50]).
agp1.fmsd 1.02.10
313
F.3.1.4 Шаблоны
В следующем примере будет описан шаблон для проецирования
прямого произведения на первый сомножитель. В текстовом стиле
шаблон оформляется следующим образом:
---- File:./src/intro/gendef.zsl
specification
generic [ X, Y ]
First : X & Y --> X
where
forall x : X; y : Y @ First (x, y) eq x
end generic
end specification
---- End Of File:./src/intro/gendef.zsl
Оформление раздела шаблонов в стиле LaTex-а:
---- File:./src/intro/gendef.zed
\begin{spec}
\begin{gendef}{X,Y}
First: X \cross Y \fun X
\where
\forall x: X; y: Y @ First(x,y) = x
\end{gendef}
\end{spec}
---- End Of File:./src/intro/gendef.zed
Вид раздела шаблонов после включения в документ LaTex-а:
[X, Y]
First : X × Y → X
∀ x : X; y : Y ∙ First(x, y) = x
agp1.fmsd 1.02.10
314
F.3.1.5 Схемы
Схемы имеют собственное имя, на которое можно ссылаться в
спецификации. Имена, которые объявляются в верхней части схемы называются переменными схемы или компонентами. Переменны
доступны только внутри текущей схемы или внутри схемы, которая
включает в себя текущую ([17, стр.52]). Предикат в нижней части
является инвариантом ([17, стр.51]).
Оформление различных видов схем можно посмотреть на примере разработки проекта Книга Дней Рождений в [20], частичный
перевод находится в разделе [30, Z и Абстрактная спецификация],
полные спецификации проекта включены в текущий отчет и находятся в разделах: абстрактная форма в разделе F.6 и императивная
форма в F.7.
F.3.1.6 Синтаксис
Раздел синтаксиса используется для свободных типов (перечислений). В этом разделе находится последовательность правил синтаксиса, которые надо разделять командой \also. В данном примере
задается правила для операций и выражений:
---- File:./src/intro/syntax.zsl
specification
OP ::= plus | minus | times | divide
EXP ::= const << Z >>
| binop << OP & EXP & EXP >>
end specification
---- End Of File:./src/intro/syntax.zsl
---- File:./src/intro/syntax.zed
agp1.fmsd 1.02.10
315
\begin{spec}
\begin{syntax}
OP & ::= & plus | minus | times | divide
\also
EXP & ::= & const \ldata \num \rdata \\
& | & binop \ldata OP \cross
EXP \cross EXP \rdata
\end{syntax}
\end{spec}
---- End Of File:./src/intro/syntax.zed
OP ::= plus | minus | times | divide
EXP ::= const⟨⟨Z⟩⟩
| binop⟨⟨OP × EXP × EXP⟩⟩
F.4
Подключение тестовой спецификации
Дистрибутив утилиты ztc содержит тестовые спецификации в разных стилях. Одна из них, сделанная под LaTex подключается ниже:
[Student]
size : N
size = 6
Response ::= success
| notenrolled
| nocert
| cert
| alreadyenrolled
| alreadytested
| noroom
agp1.fmsd 1.02.10
Class
enrolled, tested : P Student
#enrolled ≤ size
tested ⊆ enrolled
ClassInit
Class′
enrolled′ = ∅
tested′ = ∅
Enrolok
ΔClass
s? : Student
r! : Response
s? ̸∈ enrolled
#enrolled < size
enrolled′ = enrolled ∪ {s?}
tested′ = tested
r! = success
Testok
ΔClass
s? : Student
r! : Response
s? ∈ enrolled
s? ̸∈ tested
tested′ = tested ∪ {s?}
enrolled′ = enrolled
r! = success
316
agp1.fmsd 1.02.10
Leaveok
ΔClass
s? : Student
r! : Response
s? ∈ enrolled
enrolled′ = enrolled ∖ {s?}
((s? ∈ tested ∧
tested′ = tested ∖ {s?} ∧
r! = cert) ∨
(s? ̸∈ tested ∧
tested′ = tested ∧
r! = cert))
Enquire
ΞClass
s? : Student
r! : Response
((s? ̸∈ enrolled ∧
r! = notenrolled) ∨
(s? ∈ enrolled ∖ tested ∧
r! = alreadyenrolled) ∨
(s? ∈ tested ∧
r! = alreadytested))
AlreadyEnrolled
ΞClass
s? : Student
r! : Response
s? ∈ enrolled
r! = alreadyenrolled
317
agp1.fmsd 1.02.10
318
NoRoom
ΞClass
s? : Student
r! : Response
#enrolled = size
r! = noroom
AlreadyTested
ΞClass
s? : Student
r! : Response
s? ∈ tested
r! = alreadytested
NotEnrolled
ΞClass
s? : Student
r! : Response
s? ̸∈ enrolled
r! = notenrolled
Enrol == Enrolok ∨ NoRoom ∨ AlreadyEnrolled
Test == Testok ∨ NotEnrolled ∨
AlreadyTested
Leave == Leaveok ∨ NotEnrolled
Спецификация на LaTex была получена командной
ztc.exe -Il
из файла.
Classman
-Ot Classman.zed
agp1.fmsd 1.02.10
---- File:./src/test/classman.zsl
specification
[ Student ]
global
size : N
axiom
size = 6
end axiom
Response ::= success
| notenrolled
| nocert
| cert
| alreadyenrolled
| alreadytested
| noroom
%% state-schema Class
schema Class
enrolled, tested : P Student
where
# enrolled <= size;
tested subseteq enrolled
end schema
%% init-schema ClassInit
schema ClassInit
Class’
where
enrolled’ = {};
tested’ = {}
end schema
schema Enrolok
Delta Class;
s? : Student;
r! : Response
where
s? notin enrolled;
# enrolled < size;
enrolled’ = enrolled || { s? };
tested’ = tested;
319
agp1.fmsd 1.02.10
r! = success
end schema
schema Testok
Delta Class;
s? : Student;
r! : Response
where
s? in enrolled;
s? notin tested;
tested’ = tested || { s? };
enrolled’ = enrolled;
r! = success
end schema
schema Leaveok
Delta Class;
s? : Student;
r! : Response
where
s? in enrolled;
enrolled’ = enrolled \ { s? };
((s? in tested /\
tested’ = tested \ { s? } /\
r! = cert) \/
(s? notin tested /\
tested’ = tested /\
r! = cert))
end schema
%% operation Enquire
schema Enquire
Xi Class;
s? : Student;
r! : Response
where
((s? notin enrolled /\
r! = notenrolled) \/
(s? in enrolled \ tested /\
r! = alreadyenrolled) \/
(s? in tested /\
r! = alreadytested))
end schema
schema AlreadyEnrolled
Xi Class;
s? : Student;
r! : Response
320
agp1.fmsd 1.02.10
where
s? in enrolled;
r! = alreadyenrolled
end schema
schema NoRoom
Xi Class;
s? : Student;
r! : Response
where
# enrolled = size;
r! = noroom
end schema
schema AlreadyTested
Xi Class;
s? : Student;
r! : Response
where
s? in tested;
r! = alreadytested
end schema
schema NotEnrolled
Xi Class;
s? : Student;
r! : Response
where
s? notin enrolled;
r! = notenrolled
end schema
%% operation Enrol
%% operation Test
%% operation Leave
Enrol =^= Enrolok \/ NoRoom \/ AlreadyEnrolled
Test =^= Testok \/ NotEnrolled \/ AlreadyTested
Leave =^= Leaveok \/ NotEnrolled
end specification
---- End Of File:./src/test/classman.zsl
Замечание
321
agp1.fmsd 1.02.10
322
На самом деле, в выходном файле требуется заменить слово
eq на символ =, и отступы с табуляциями вида ’∖t2’ в начале
строки. При помощи потоко ориентированного редактора sed
это выполняется следующими командами:
sed.exe ’s/ eq / = /’ Classman.zed
sed.exe ’s/^.t[1-9]/ /’ Classman.zed
(см. раздел F.1.1.1 ).
Чуть более красивую спецификацию можно получить командой:
ztc.exe -Il
y -Ot Classman.zbx
---- File:./src/test/classman.zbx
specification
[ Student ]
| size : N
|-------------------------------| size = 6
Response ::= success
| notenrolled
| nocert
| cert
| alreadyenrolled
| alreadytested
| noroom
%% state-schema Class
--- Class ------------------------------------------------| enrolled, tested : P Student
|-------------------------------| # enrolled <= size;
| tested subseteq enrolled
----------------------------------------------------------%% init-schema ClassInit
agp1.fmsd 1.02.10
--- ClassInit --------------------------------------------| Class’
|-------------------------------| enrolled’ = {};
| tested’ = {}
------------------------------------------------------------- Enrolok ----------------------------------------------| Delta Class;
| s? : Student;
| r! : Response
|-------------------------------| s? notin enrolled;
| # enrolled < size;
| enrolled’ = enrolled || { s? };
| tested’ = tested;
| r! = success
------------------------------------------------------------- Testok -----------------------------------------------| Delta Class;
| s? : Student;
| r! : Response
|-------------------------------| s? in enrolled;
| s? notin tested;
| tested’ = tested || { s? };
| enrolled’ = enrolled;
| r! = success
------------------------------------------------------------- Leaveok ----------------------------------------------| Delta Class;
| s? : Student;
| r! : Response
|-------------------------------| s? in enrolled;
| enrolled’ = enrolled \ { s? };
| ((s? in tested /\
|
tested’ = tested \ { s? } /\
|
r! = cert) \/
|
(s? notin tested /\
|
tested’ = tested /\
|
r! = cert))
----------------------------------------------------------%% operation Enquire
--- Enquire -----------------------------------------------
323
agp1.fmsd 1.02.10
| Xi Class;
| s? : Student;
| r! : Response
|-------------------------------| ((s? notin enrolled /\
|
r! = notenrolled) \/
|
(s? in enrolled \ tested /\
|
r! = alreadyenrolled) \/
|
(s? in tested /\
|
r! = alreadytested))
------------------------------------------------------------- AlreadyEnrolled --------------------------------------| Xi Class;
| s? : Student;
| r! : Response
|-------------------------------| s? in enrolled;
| r! = alreadyenrolled
------------------------------------------------------------- NoRoom -----------------------------------------------| Xi Class;
| s? : Student;
| r! : Response
|-------------------------------| # enrolled = size;
| r! = noroom
------------------------------------------------------------- AlreadyTested ----------------------------------------| Xi Class;
| s? : Student;
| r! : Response
|-------------------------------| s? in tested;
| r! = alreadytested
------------------------------------------------------------- NotEnrolled ------------------------------------------| Xi Class;
| s? : Student;
| r! : Response
|-------------------------------| s? notin enrolled;
| r! = notenrolled
----------------------------------------------------------%% operation Enrol
324
agp1.fmsd 1.02.10
%% operation Test
%% operation Leave
Enrol =^= Enrolok \/ NoRoom \/ AlreadyEnrolled
Test =^= Testok \/ NotEnrolled \/ AlreadyTested
Leave =^= Leaveok \/ NotEnrolled
end specification
---- End Of File:./src/test/classman.zbx
F.5
Z и шаблоны схем
---- File:./src/bowen/g.zsl
% %
я пытался ввести операции как у Боема, получились просто функции.
% %
и ошибка в определении
spec
generic [T]
for : (seq T) & N fun (seq T);
after : (seq T) & N fun (seq T)
where
forall s: seq T; n:N @
for (s, n) = (1..n) dres s
and
after(s, n) = ({0} dsub
succ ^ (n) ) comp s
end generic
end spec
---- End Of File:./src/bowen/g.zsl
[T]
: (seq T) × N → (seq T)
∀ s : seq T; n : N ∙ (sforn = (1 . . n)
Cs ∧
saftern = ({0} −
C succ a (n)) o9 s)
325
agp1.fmsd 1.02.10
F.6
326
Абстрактная форма спецификации Книга Дней Рождений
См. [20, The birthday book], [30, СПЕЦИФИКАЦИЯ ПРОЕКТА ’КНИГА ДНЕЙ РОЖДЕНИЙ’].
[NAME, DATE]
BirthdayBook
known : P NAME
birthday : NAME →
↦ DATE
known = dom birthday
AddBirthday
ΔBirthdayBook
name? : NAME
date? : DATE
name? ̸∈ known
birthday′ = birthday ∪ {name? ↦→ date?}
FindBirthday
ΞBirthdayBook
name? : NAME
date! : DATE
name? ∈ known
date! = birthday(name?)
Remind
ΞBirthdayBook
today? : DATE
cards! : P NAME
cards! = {n : known | birthday(n) = today?}
agp1.fmsd 1.02.10
InitBirthdayBook
BirthdayBook
known = ∅
REPORT ::= ok | already known | not known
Success
result! : REPORT
result! = ok
AlreadyKnown
ΞBirthdayBook
name? : NAME
result! : REPORT
name? ∈ known
result! = already known
RADDB
ΔBirthdayBook
name? : NAME
date? : DATE
result! : REPORT
(name? ̸∈ known ∧
birthday′ = birthday ∪ {name? ↦→ date?} ∧
result! = ok) ∨
(name? ∈ known ∧
birthday′ = birthday ∧
result! = already known)
327
agp1.fmsd 1.02.10
328
NKN
ΞBirthdayBook
name? : NAME
result! : REPORT
name? ̸∈ known
result! = not known
RFNDB == (FindBirthday ∧ Success) ∨ NKN
F.7
Императивная форма спецификации Книга Дней
Рождений
[NAME, DATE]
BirthdayBook
known : P NAME
birthday : NAME →
↦ DATE
known = dom birthday
BirthdayBook1
names : N1 → NAME
dates : N1 → DATE
hwm : N
∀ i, j : 1 . . hwm ∙ (i ̸= j ⇒
names(i) ̸= names(j))
Abs
BirthdayBook
BirthdayBook1
known = {i : 1 . . hwm ∙ names(i)}
∀ i : 1 . . hwm ∙ birthday(names(i)) = dates(i)
agp1.fmsd 1.02.10
AddBirthDay1
ΔBirthdayBook1
name? : NAME
date? : DATE
∀ i : 1 . . hwm ∙ name? ̸= names(i)
hwm′ = hwm + 1
names′ = names ⊕ {hwm′ ↦→ name?}
dates′ = dates ⊕ {hwm′ ↦→ date?}
FindBirthday1
ΞBirthdayBook1
name? : NAME
date! : DATE
∃ i : 1 . . hwm ∙ (name? = names(i) ∧
date! = dates(i))
AbsCards
cards : P NAME
cardlist : N1 → NAME
ncards : N
cards = {i : 1 . . ncards ∙ cardlist(i)}
Remaind1
ΞBirthdayBook1
today? : DATE
cardslist! : N1 → NAME
ncards! : N
{i : 1 . . ncards! ∙ cardslist!(i)} = {j : 1
. .hwm | dates(j) = today? ∙ names(j)}
329
agp1.fmsd 1.02.10
InitBirthdayBook1
BirthdayBook1
hwm = 0
330
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )