Спецификация структур данных и программ
Этот материал представляет собой терминологический справочник по спецификации структур данных и программ, включающий контрольные вопросы, основные компоненты и элементы нотации.
Суть вопроса
Структуры данных описываются формально через модели, типы, инварианты и схемы. Программные структуры определяются через интерфейсы, предусловия и постусловия, состояния и потоки управления. Цель такого подхода — создание однозначной, тестируемой и поддерживаемой архитектуры.
Краткое профессиональное описание
Спецификация данных
- Модели: ER-диаграмма или UML-диаграмма классов
- Кардинальность, ключи, нормализация (до 3NF)
- Правила как инварианты
- Интерфейсные данные в машиночитаемом виде: JSON Schema (или DDL/XML Schema)
Спецификация программ
- Модули и APIs с сигнатурами
- Контракты на ошибки
- Design by Contract: предусловие, постусловие, инвариант
- Поведение: автоматы состояний, диаграммы активности и последовательности
- Уточнение: Object Constraint Language (OCL)
Спецификации служат основой для автоматической валидации, генерации заглушек и Contract Tests.
Важные моменты для подготовки
- Кардинальность и ключи — корректно: Модели данных должны определять уникальные ключи и правильные связи между сущностями. Неправильно установленная кардинальность приводит к несогласованным данным или ошибочным запросам.
- JSON Schema для валидации входных данных: JSON Schema описывает допустимые структуры и диапазоны значений для JSON-данных. С его помощью можно проверять входные данные ещё до обработки и отклонять некорректные данные.
- Предусловия, постусловия и обработка ошибок: Design by Contract формулирует обязательства для вызывающего и вызываемого кода. Предусловия должны выполняться до вызова, постусловия — после. Ошибочные случаи явно определяются как исключения.
- Модели состояний для допустимых переходов: Диаграммы состояний показывают, в каких состояниях может находиться объект и какие переходы допустимы. Это предотвращает недопустимые изменения состояния, например повторную отправку отменённого заказа.
- Вывод тестовых случаев (классы эквивалентности и граничные значения): Из спецификаций можно целенаправленно разрабатывать тестовые случаи. Инварианты и условия дают классы эквивалентности, ключи и границы — конкретные тестовые данные.
- Версионирование, миграция и снятие с поддержки: Схемы и интерфейсы меняются со временем. Семантическое версионирование, объявления об устаревании и пути миграции помогают контролируемо внедрять изменения.
- Безопасность: валидация, права доступа и поля аудита: Спецификации должны включать аспекты безопасности. Это включает валидацию входных данных, права доступа и логирование, кто, когда и какие данные изменил.
Основные компоненты
- Абстрактный тип данных + область значений — Абстрактный тип данных определяет возможные значения и операции над структурой данных. Область значений определяет, какие входные данные корректны, например положительные числа или строки с определённым шаблоном.
- Модель структуры (ER/класс) — ER-диаграмма или UML-диаграмма классов описывает сущности, их атрибуты и связи. Модель структуры лежит в основе базы данных и объектных моделей.
- Кардинальность + нормальные формы — Кардинальность указывает, сколько сущностей связаны друг с другом. Нормальные формы снижают избыточность и предотвращают аномалии при вставке, обновлении и удалении.
- Схема данных (JSON Schema) — JSON Schema — это машиночитаемое описание JSON-данных. Оно задаёт типы, обязательные поля, диапазоны значений и шаблоны, позволяя автоматизировать валидацию.
- API-контракт + коды ошибок — API-контракт описывает интерфейсы, параметры, возвращаемые значения и обработку ошибок. Коды ошибок и сообщения помогают вызывающему коду распознавать проблемы и обрабатывать их корректно.
- Design by Contract — Design by Contract определяет предусловия, постусловия и инварианты. Это гарантирует, что вызывающий и вызываемый код соблюдают свои обязательства, и упрощает отладку.
- Модели состояния и процесса — Модели состояния показывают допустимые состояния и переходы. Модели процесса вроде диаграмм активности описывают потоки выполнения и решения внутри логики программы.
- Правила качества (NFR) — Нефункциональные требования вроде производительности, безопасности или доступности формулируются как правила качества. Они дополняют функциональную спецификацию измеримыми критериями.
- Вывод тестов (Contract/Property) — Из спецификаций можно вывести тестовые случаи. Contract Tests проверяют контракты интерфейсов, Property-based Tests проверяют общие свойства вроде инвариантов.
- Концепция версионирования и миграции — Изменения схем и APIs должны версионироваться. Концепция миграции описывает, как существующие данные и клиенты переводятся на новые версии.
Практический пример (заказ)
JSON Schema (отрывок в текстовом виде)
type: object
required: id, kundeId, positionen, gesamt
properties:
id: string (pattern ^ORD-[0-9]{6}$)
gesamt: number (minimum 0)
positionen: array (minItems 1)
OCL-инварианты (в смысле)
context Bestellung inv SummeStimmt:
gesamt = sum(positionen.preis * positionen.menge)
context Bestellung inv PositiveMengen:
forAll(positionen, menge > 0)
Контракт сервиса (псевдокод)
interface BestellService
legeBestellungAn(warenkorb)
vorbedingung:
warenkorb.positionen nicht leer und warenkorb.gesamt > 0
nachbedingung:
result.status = ANGELEGT und result.gesamt = warenkorb.gesamt
fehlerfälle:
UngültigeDaten, ZahlungAbgelehnt
Преимущества и недостатки
Преимущества
- Однозначная коммуникация
- Автоматизируемая валидация
- Лучшая тестируемость и меньше ошибок интеграции
Недостатки
- Первоначальные затраты
- Поддержка версий и миграций
- Риск излишней формализации
Типичные контрольные вопросы (с кратким ответом)
- ER-диаграмма или диаграмма классов? ER для данных и персистентности, класс для типов и операций.
- Зачем нужны инварианты? Это правила, которые должны всегда выполняться.
- Как из спецификации получить тесты? Предусловия и инварианты переводят в классы эквивалентности и граничные значения.
- Как безопасно версионировать схемы? Семантическое версионирование, Breaking Changes равны Major, объявления об устаревании и миграция.
Стратегия изучения
- Введение в понимание: Смоделируйте небольшую предметную область, например библиотеку или интернет-магазин, в виде диаграммы классов. Выведите из неё JSON Schema и несколько инвариантов.
- Метод углубления: Сформулируйте для существующей функции предусловия, постусловия и обработку ошибок. Напишите на их основе тестовые случаи, используя классы эквивалентности и граничные значения.
- Тренировка к экзамену: Потренируйтесь различать ER-диаграмму и диаграмму классов, а также правильно записывать инварианты и переходы состояния.
- Избежание ошибок: Держите спецификации в актуальном состоянии. Когда система меняется, модель, схема и контракты должны обновляться, иначе накапливается технический долг.
Практическое упражнение 1: JSON Schema для заказа
Заказ имеет ID в формате ORD- плюс шесть цифр, ID клиента, минимум одну позицию и общую сумму, которая должна быть больше или равна нулю. JSON Schema формально закрепляет эти правила и может автоматически проверять входные данные.
Практический пример 2: OCL-инварианты для заказа
Заказ должен соответствовать инварианту, при котором общая сумма равна сумме всех позиций. Другой инвариант требует, чтобы каждое количество было положительным. Такие инварианты можно преобразовать в тесты.
Практический пример 3: Design by Contract для сервиса заказов
Функция legeBestellungAn требует предусловие: непустую корзину с положительной суммой. Постусловие гарантирует, что заказ получит статус ANGELEGT и сумма будет верной. Ошибочные ситуации, такие как неверные данные или отклоненный платёж, описаны явно.
Упражнение 1: выбор типа модели
Вы хотите задокументировать структуру данных для реляционной базы данных. Какая модель подходит лучше: ER-модель или диаграмма классов?
Решение: ER-модель подходит лучше, поскольку представляет сущности, атрибуты и связи для проектирования базы данных. Диаграмма классов сосредоточена больше на типах, операциях и наследовании.
Упражнение 2: вывести инвариант
Позиция заказа имеет атрибуты preis и menge. Сформулируйте подходящий инвариант.
Решение: Подходящий инвариант: menge > 0 и preis >= 0. Оба условия должны выполняться всегда, чтобы позиция была корректной.
Упражнение 3: объяснить модель состояний
Заказ может находиться в состояниях ANGELEGT, BEZAHLT, VERSENDET и STORNIERT. Какие переходы имеют смысл, какие нет?
Решение: Осмысленные переходы: ANGELEGT → BEZAHLT, BEZAHLT → VERSENDET и ANGELEGT → STORNIERT. Бессмысленны VERSENDET → ANGELEGT и STORNIERT → VERSENDET, так как они нарушают бизнес-процесс.
Анализ темы
- Технический стержень: Формальное описание данных и поведения. Спецификации определяют, какие данные допустимы и как система должна себя вести. Модели, схемы и контракты — центральные инструменты.
- Вызовы реализации: Баланс между точностью и практичностью. Чрезмерно формальные спецификации дорогостоящи в поддержке, слишком неточные приводят к неправильному пониманию. Подходящая степень детализации зависит от проекта.
- Аспекты безопасности: Валидация и права как часть спецификации. Проверка входных данных, контроль доступа и журналы аудита должны учитываться в спецификации, чтобы они не были забыты при реализации.
- Требования документирования: Модели, схемы и контракты как документация проекта. Спецификации — обязательная часть проектной документации. Они помогают согласовать требования между бизнесом, разработкой и тестированием.
- Экономическая оценка: Затраты на спецификацию против экономии от меньшего количества ошибок. Хорошая спецификация требует времени в начале, но предотвращает дорогостоящие ошибки и переделки на поздних этапах. Автоматизируемая валидация и получение тестов повышают ценность.



