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

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

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

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

Опора — Раздел 26: проектирование процедурной программы. Дополнительно используется весь инструментарий Разделов 1–25.

Каждая задача оформляется как отдельная консольная программа полного формата курса и компилируется с <Nullable>enable</Nullable>. До написания или изменения кода создаётся паспорт решения: назначение; внешнее поведение; входы и выходы; допустимые, граничные и недопустимые данные; критерии успеха и отказа; модель состояния; выбранное представление и минимум одна альтернатива; таблица методов с ответственностью, параметрами, результатом, предусловиями, постусловиями и побочными эффектами; схема зависимостей; план проверки с ожидаемыми результатами; оценка времени и дополнительной памяти; этапы реализации. Разрешены только конструкции Разделов 1–26. Классы предметной области, свойства, пользовательские конструкторы, интерфейсы, обобщённые коллекции, LINQ, делегаты, лямбда-выражения, асинхронность и многопоточность запрещены. Дискретный переход состояния, управляющий цикл симуляции и исследовательские серии траекторий относятся к Разделу 27 и в модуле не используются. Вычисляющие методы не выполняют консольный или файловый ввод-вывод; Random, Stopwatch, пути и настройки являются явными зависимостями. После каждого этапа выполняется полный регрессионный набор ранее подтверждённого поведения.


База практических заданий

Уровень I. Базовый

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

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

static bool TryParseCoefficients(
    string[] input,
    out double a,
    out double b,
    out double c,
    out string error)

static EquationResult SolveEquation(
    double a,
    double b,
    double c,
    double tolerance)

static string FormatResult(
    EquationResult result)

Объявить EquationKind и EquationResult с указанными в паспорте полями. SolveEquation не работает со строками и консолью, FormatResult не выполняет вычислений. Значения NaN, бесконечности и отрицательный допуск отвергаются до вычисления. Сохранить прежние тексты и результаты для всех случаев.

2. Статистика и фильтрация массива: Монолитная программа для непустого массива целых вычисляет сумму long, среднее, минимум, максимум, число положительных элементов и формирует новый массив значений не меньше порога. Выделить:

static ArraySummary Analyze(int[] data)

static int CountAtLeast(
    int[] data,
    int threshold)

static int[] FilterAtLeast(
    int[] data,
    int threshold)

static string FormatSummary(
    ArraySummary summary)

ArraySummary объявить как struct. Фильтрация выполняется двумя проходами и сохраняет порядок. Вычисляющие методы не изменяют исходный массив. Нарушение предусловия Analyze обрабатывается внешней границей до вызова.

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

static int[] CopyOf(int[] source)

static int LowerBound(
    int[] sorted,
    int target)

static int UpperBound(
    int[] sorted,
    int target)

static SearchRange FindRange(
    int[] source,
    int target)

static string FormatSearchResult(
    SearchRange result)

Оба поиска используют одну модель [lo, hi). FindRange сохраняет исходный массив. Паспорт фиксирует, является ли пустой диапазон отсутствием цели и какие индексы возвращаются для цели меньше минимума и больше максимума.

4. Отчёт по прямоугольной таблице: Монолитная программа для int[,] вычисляет суммы строк и столбцов, транспонированную копию и координаты первого максимума в построчном порядке. Выделить:

static long[] RowSums(int[,] data)

static long[] ColumnSums(int[,] data)

static int[,] Transpose(int[,] data)

static CellMaximum FindFirstMaximum(
    int[,] data)

static string[] FormatMatrixReport(
    int[,] source,
    long[] rowSums,
    long[] columnSums,
    int[,] transpose,
    CellMaximum maximum)

Предусловие поиска максимума — наличие хотя бы одной ячейки. Формы всех результатов и отображение координат фиксируются в контрактах. Форматирование не повторяет вычисления.

5. Нормализация текстовой записи: Исходная программа обрабатывает строку:

surname;score;comment

Требования: ровно три поля, пустой комментарий допустим, score разбирается как конечный double в InvariantCulture, краевые пробелы удаляются, внутренние пробельные серии текстовых полей заменяются одним пробелом. Выделить:

static bool TrySplitRecord(
    string text,
    out string surname,
    out string scoreText,
    out string comment,
    out RecordError error)

static bool TryParseScore(
    string text,
    out double score)

static string NormalizeTextField(
    string text)

static string FormatMachineRecord(
    TextRecord record)

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

6. Калькулятор канонических дробей: Монолитная программа создаёт две дроби, нормализует их, складывает, вычитает, умножает и выводит результаты. Объявить Fraction и выделить:

static bool TryCreateFraction(
    long numerator,
    long denominator,
    out Fraction result)

static bool TryAdd(
    Fraction left,
    Fraction right,
    out Fraction result)

static bool TrySubtract(
    Fraction left,
    Fraction right,
    out Fraction result)

static bool TryMultiply(
    Fraction left,
    Fraction right,
    out Fraction result)

static bool IsCanonical(
    Fraction value)

static string FormatFraction(
    Fraction value)

Каждый успешный результат сокращён, имеет положительный знаменатель и представляет ноль как 0/1. Предусловие исключает long.MinValue там, где требуется вычислять модуль. Контроль переполнения выполняется в checked, а отказ арифметики не публикует частично построенную дробь.

7. Отчёт по занятым интервалам: Монолитная программа получает массив полуоткрытых интервалов одного дня, сортирует независимую копию, объединяет пересекающиеся и соприкасающиеся интервалы и вычисляет свободные промежутки рабочего окна. Представление и методы заданы:

public struct TimeInterval
{
    public DateTime Start;
    public DateTime End;
}

static bool AreValid(
    TimeInterval[] intervals)

static TimeInterval[] CopyAndSort(
    TimeInterval[] intervals)

static TimeInterval[] Merge(
    TimeInterval[] sorted)

static TimeInterval[] FindFree(
    TimeInterval workWindow,
    TimeInterval[] merged)

static string[] FormatSchedule(
    TimeInterval[] busy,
    TimeInterval[] free)

Ни один метод не изменяет входной массив. Контракты фиксируют политику касания границ и пустого набора.

8. Воспроизводимая гистограмма: Монолитная программа бросает шестигранную кость с фиксированным seed, строит гистограмму и печатает частоты. Выделить:

static int[] GenerateRolls(
    Random rng,
    int count)

static int[] BuildHistogram(
    int[] rolls)

static HistogramSummary AnalyzeHistogram(
    int[] counts)

static string[] FormatHistogram(
    int[] counts,
    HistogramSummary summary)

Генератор создаётся только в Main. Методы анализа не зависят от Random. Повтор всего сценария с новым генератором того же зерна должен давать идентичные броски, счётчики и строки отчёта.

9. Серия измерений алгоритма: Монолитная программа измеряет линейный поиск на нескольких размерах. Выделить:

static int[] BuildInput(int size)

static void WarmUp(
    int[] data,
    int target)

static long[] MeasureSeries(
    int[] data,
    int target,
    int repetitions)

static TimingSummary AnalyzeTimings(
    long[] ticks)

static string[] FormatTimingReport(
    int size,
    TimingSummary summary)

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

10. Импорт машинных записей: Монолитная программа читает файл id;value, прекращает разбор при первой повреждённой строке и записывает статистику корректного набора. Выделить:

static string[] ReadLines(string path)

static bool TryParseRecords(
    string[] lines,
    out Record[] records,
    out DataError error)

static RecordSummary AnalyzeRecords(
    Record[] records)

static string[] FormatReport(
    RecordSummary summary)

static void WriteReport(
    string path,
    string[] lines)

Файловые исключения обрабатываются только в Main; ошибки содержимого возвращаются логически с номером строки и причиной. При ошибке разбора существующий выходной файл не создаётся и не изменяется.

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

static string LoadPart(string path)

static string[] BuildDocument(
    string header,
    string body,
    string conclusion)

static bool ValidateDocument(
    string[] lines,
    out string error)

static void WriteTemporaryCandidate(
    string path,
    string[] lines)

static void PublishCandidate(
    string temporaryPath,
    string targetPath)

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

12. Реестр с фиксированной вместимостью: Дана монолитная программа, которая хранит активный префикс массива RegistryEntry[], выполняет заранее подготовленную последовательность команд и сохраняет реестр в файл. Архитектура задана:

static bool TryAdd(
    RegistryEntry[] entries,
    ref int count,
    RegistryEntry value,
    out RegistryError error)

static bool TryUpdate(
    RegistryEntry[] entries,
    int count,
    RegistryEntry value,
    out RegistryError error)

static bool TryRemove(
    RegistryEntry[] entries,
    ref int count,
    int id,
    out RegistryError error)

static int FindIndexById(
    RegistryEntry[] entries,
    int count,
    int id)

static void StableSort(
    RegistryEntry[] entries,
    int count)

static string[] FormatActive(
    RegistryEntry[] entries,
    int count)

static bool TryParseFile(
    string[] lines,
    RegistryEntry[] destination,
    out int count,
    out DataError error)

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


Уровень II. Продвинутый

Дано только требуемое внешнее поведение, ограничения и критерии качества. До реализации требуется самостоятельно создать полный паспорт решения, выбрать представление, систему методов, границы ответственности, политику отказа и порядок этапов. В отличие от Уровня I ученик проектирует архитектуру с нуля и обязан показать, почему выбранное разбиение делает корректность и проверку проще допустимых альтернатив.

1. Протокол экзамена: Файл содержит:

studentId;name;task1;task2;task3

Оценки — целые от 0 до 100. Требуется собрать все построчные ошибки, отклонить весь протокол при повторе идентификатора, вычислить итог по весам 0.2, 0.3, 0.5, определить статус допуска и сформировать устойчивый рейтинг:

  1. больший итог раньше;
  2. затем имя по StringComparison.Ordinal;
  3. затем исходный номер строки.

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

2. Планировщик занятых интервалов: Входной файл содержит интервалы одного дня:

HH:mm;HH:mm

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

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

  • прямоугольный массив с заполнителем;
  • прямоугольный массив с маской присутствия;
  • зубчатый массив.

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

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

transpose
rotate
flip-h
flip-v

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

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

5. Анализ текстового корпуса: Дан массив строк. Для каждой строки требуется определить число кодовых единиц, букв, цифр, пробельных символов и слов, где словом считается максимальная непустая серия непробельных кодовых единиц; для корпуса — частоты ASCII-букв без учёта регистра, первую самую длинную строку и нормализованную копию текста. Алгоритм работает по char и не заявляет поддержку графем. Самостоятельно выбрать структуры результата, число проходов, представление частот, способ сборки текста и формат отчёта.

6. Разреженный многочлен: Многочлен хранится массивом членов (degree, coefficient). Требуется прочитать два многочлена, проверить строгий порядок степеней, уникальность степеней, конечность коэффициентов и отсутствие значений в пределах нулевого допуска, сложить их слиянием, получить производную, вычислить значения в заданных точках и записать канонический результат. Спроектировать Term, инварианты, методы разбора, проверки, сложения, вычисления и форматирования. Сравнить с плотным массивом коэффициентов.

7. Пакет изменений товарных остатков: Исходный файл содержит уникальные товары, второй — последовательность изменений code;delta. Повторные изменения одного кода разрешены. Требуется проверить оба файла, вычислить итоговые количества без изменения подтверждённого состояния, отвергнуть неизвестный код, переполнение и отрицательный остаток и опубликовать новый каталог только при полном успехе. Самостоятельно выбрать структуры, способ поиска, промежуточное состояние, диагностический контракт и порядок публикации.

8. Аудит случайного отбора: Из массива кандидатов требуется равномерно выбрать k различных записей с фиксированным seed, сохранить исходные индексы и сформировать проверяемый отчёт. Дополнительно программа проводит серии для малого набора и сравнивает частоты всех подмножеств. Спроектировать границу генератора, алгоритм выборки, структуру результата, способ проверки воспроизводимости и отделение рабочего выбора от статистического эксперимента.

9. Исследование двух алгоритмов: Требуется сравнить линейный и бинарный поиск на одинаковых массивах и запросах для серии размеров. Спроектировать:

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

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

10. Консолидация каталога измерений: Каталог содержит файлы:

timestamp;channel;value

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

11. Реестр команд: Разработать программу с фиксированной вместимостью реестра записей id, name, score, поддерживающую команды:

add
update
remove
find
sort
list
save
load
exit

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

12. Аудиторский пакет с несколькими результатами: Несколько входных файлов содержат взаимосвязанные справочники и операции. Требуется сформировать:

  • нормализованные копии каждого входа;
  • сводный отчёт;
  • полный отчёт диагностик;
  • манифест с числом записей и контрольными суммами.

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


Уровень III. Экспертный

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

1. Разреженная таблица большого размера: Логическая таблица имеет до 10_000 × 10_000 позиций, но содержит не более 100_000 реальных значений. Требуются загрузка троек (row, column, value), проверка уникальности координат, чтение отдельной позиции, суммы строк, транспонирование и запись результата.

Сравнить:

  1. double[,] и bool[,];
  2. единый массив Cell;
  3. зубчатый массив строк из Cell.

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

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

Сравнить:

  1. массив кодированных событий с сортировкой;
  2. одномерный массив разностей длины 7 * 1440 + 1, где последняя ячейка хранит правую границу недельного полуинтервала.

До реализации вывести оценки:

O(klogk)O(k\log k)

и

O(k+71440).O(k+7\cdot1440).

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

3. Первые k записей рейтинга: Дан массив до 200_000 результатов, а требуется только первая сотня по составному порядку:

  1. больший балл;
  2. меньший штраф;
  3. имя по Ordinal;
  4. исходный номер.

Сравнить:

  • полную процедурную сортировку O(n²);
  • упорядоченный буфер длины k за O(nk);
  • самостоятельно реализованную устойчивую сортировку слиянием всей копии за O(n log n) и с дополнительной памятью O(n).

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

4. Версионирование машинного формата: Первая версия файла содержит:

id;name;score

Вторая использует формат id;name;score;status;timestamp;comment, добавляет обязательные status и timestamp, допускает пустой комментарий и требует заголовок версии. Старые файлы должны продолжать читаться и преобразовываться в единую внутреннюю модель.

Сравнить:

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

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

5. Пакетный импорт с согласованной публикацией: Несколько входных файлов должны породить единый каталог записей, общий отчёт и нормализованные копии. Сравнить прямое изменение постоянных результатов по мере обработки с предварительным построением всех кандидатов в памяти и временных файлах.

Спроектировать:

  • модель состояния операции;
  • перечень допустимых состояний после каждого отказа;
  • границы try, catch и finally;
  • критерий начала фиксации;
  • инъекции отказа на чтении, разборе, записи кандидата и публикации.

Доказать гарантию только для этапов, которые действительно контролируются средствами курса.

6. Изменение требований к системе оценок: Первая версия хранит полную прямоугольную таблицу: одинаковое число заданий, каждая ячейка заполнена, итог — взвешенная сумма. После подтверждения вводятся требования:

  • число заданий различается по направлениям;
  • часть результатов отсутствует;
  • веса задаются отдельно;
  • старый файловый формат продолжает читаться;
  • результаты старых наборов не меняются.

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

7. Эволюция реестра без разрушения контракта: Исходная версия реестра использует фиксированный массив и один файл снимка. Последовательно добавляются:

  1. журнал команд;
  2. восстановление из снимка и журнала;
  3. второй формат снимка;
  4. ограничение времени загрузки;
  5. требование сохранять прежние команды и сообщения.

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

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

До кода подготовить три архитектуры:

  1. этапы, работающие непосредственно с исходными строками;
  2. единая каноническая модель после полного разбора;
  3. частичные предметные модели для каждого входа с последующим объединением.

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


Обязательные контрольные наборы

ЗадачаПодготовленные данные и критерий
I.1два корня, один корень, отсутствие вещественных корней, линейный, тождественный и противоречивый случаи; неверное число строк
I.2[4,-2,7,0,7], пороги 0, 7, 10; пустой массив как нарушение предусловия
I.3[8,3,5,3,9,3,1], цели 3, 4, 0, 10
I.4таблицы 1 × 1, 2 × 3, 3 × 2; повторяющийся максимум
I.5" Ivanov ; 91.5 ; "; лишнее поле; неверный балл; пустой комментарий
I.61/2 и -3/4; нулевой знаменатель; сокращение до нуля; переполнение
I.7пустой набор, раздельные, касающиеся, пересекающиеся и вложенные интервалы
I.8seed = 2026, 60_000 бросков; повтор всего сценария
I.9размеры 1_000, 10_000, 100_000; присутствующие и отсутствующие цели
I.10корректный файл; повреждённые id, value; NaN; отсутствующий вход
I.11три существующие части; отсутствие каждой части; неверное содержимое; отказ до публикации
I.12добавление до вместимости, повтор идентификатора, обновление отсутствующего, удаление первого/среднего/последнего, успешная и повреждённая загрузка
II.1корректные записи, повтор studentId, оценки 0 и 100, равные итоги и одинаковые имена
II.2раздельные, касающиеся, пересекающиеся, вложенные и нулевые интервалы; неверный формат
II.3отсутствующая группа, пустая группа, длины работ 1, 3, 7
II.4таблица 2 × 3; пустая последовательность; неизвестная команда; четыре поворота
II.5пустая строка, ASCII, кириллица, пробельные серии и суррогатная пара
II.6два корректных многочлена; повтор степени; NaN; почти нулевой коэффициент
II.7корректный каталог; повторные изменения; неизвестный код; отрицательный итог; переполнение
II.8(n,k) = (5,2) для частот и (100,10) для рабочего выбора
II.9не менее шести размеров, присутствующие и отсутствующие запросы, 21 повтор
II.10два корректных файла, повреждённые строки в двух файлах и исчезнувший после перечисления вход
II.11добавление до вместимости, повтор id, удаление первого/среднего/последнего, сортировка, сохранение и повреждённая загрузка
II.12три взаимосвязанных файла; построчные ошибки; отсутствующая ссылка; отказ временной записи
III.1форма 10_000 × 10_000, до 100_000 троек; пустые строки и повтор координаты
III.2касающиеся и вложенные интервалы, границы дня, переход между днями по установленной политике
III.3n ∈ {0,1,100,10_000}, k ∈ {1,10,100}, множество равных ключей
III.4корректные версии 1 и 2; неизвестная версия; повреждённый старый и новый файл
III.5отказ чтения, ошибка формата, отказ временной записи и отказ между фиксациями
III.6старый прямоугольный набор и направления с длинами 2, 5, 8, пропусками и разными весами
III.7старый снимок, новый снимок, журнал с повреждённой последней командой и возрастающие объёмы
III.8корректный пакет, межфайловая ошибка, разные seed, отказ каждого этапа и два диапазона размеров

Итог модуля

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

Покрытие опоры и границы

  • Входы, выходы, допустимые значения, ограничения и критерии успеха: паспорт каждого решения; I.1–I.12, II.1–II.12, III.1–III.8.
  • Модель состояния, инварианты, предусловия и постусловия: I.2–I.7, I.12; II.1–II.12; III.1–III.8.
  • Разделение получения, проверки, вычисления, представления и сохранения: I.1, I.5, I.8–I.12; II.1–II.12; III.4–III.8.
  • Методы с одной ответственностью и явные зависимости: все задачи; особенно I.8–I.12, II.7–II.12 и III.5–III.8.
  • Выбор между отдельными значениями, enum, кортежем, массивами, строкой и struct: I.1–I.8, I.12; II.1–II.8, II.11–II.12.
  • Выбор прямоугольного, зубчатого, плотного и разреженного представления: I.4, II.3–II.4, II.6, III.1–III.2, III.6, III.8.
  • Цена копирования и дополнительной памяти: I.3–I.4, I.7, I.11–I.12; II.3, II.6–II.12; III.1–III.8.
  • Обычные, граничные, пустые, минимальные и недопустимые случаи: обязательные наборы всех задач.
  • Ручная трассировка, инварианты и независимая проверка методов: I.1–I.12; самостоятельно проектируются в II.1–II.12 и III.1–III.8.
  • Оценка времени и памяти и сравнение альтернатив: I.3, I.8–I.9; II.3, II.6, II.8–II.12; III.1–III.8.
  • Минимальный работающий путь и поэтапное расширение: I.1–I.12; II.1–II.12; особенно III.6–III.8.
  • Сохранение поведения при рефакторинге: I.1–I.12.
  • Изменение требований и обратная совместимость: III.4, III.6–III.8.
  • Отказы, частичное состояние и согласованная публикация: I.10–I.12, II.7, II.10–II.12, III.5, III.7–III.8.
  • Воспроизводимая случайность и честный измерительный протокол как явные зависимости: I.8–I.9, II.8–II.9, III.8.
  • Обоснование выбранного решения и известных ограничений: все задачи Уровней II–III.

За границей: Раздел 27 рассматривает дискретную симуляцию с явным переходом current → next, управляющим циклом, сериями траекторий и исследовательским отчётом. Объектно-ориентированная инкапсуляция, интерфейсы, обобщённые коллекции, делегаты, внедрение зависимостей через объекты, автоматические тестовые фреймворки, асинхронность, многопоточность и промышленные архитектурные шаблоны относятся к Курсу II. Модуль не требует изображать процедурное решение как объектную систему: качество определяется ясностью спецификации, потока данных, контрактов, доказательств и границ ответственности.