Перейти к содержанию

M1: Парсер лабораторных данных

Первая содержательная веха. Стажёр реализует парсер, который читает лабораторные данные в формате CSV или JSON и превращает их в доменные объекты (Project → Borehole → Sample → Sample_Lab → ParameterValue). Парсер становится ядром проекта защиты, поверх которого на следующих вехах наращиваются персистентность (M2), API (M3) и UI (M4).

Срок

Месяцы 1–2 Фазы 1 (~80–120 часов). Это основная по трудоёмкости веха: на ней осваивается весь фундамент C#.

Цель

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

Целевые навыки

Бриф требует явно указать целевую функцию задачи. На M1 осваивается:

Группа навыков Что конкретно
Типы: значимые и ссылочные Понимание разницы между int/double/struct и class/string. Когда что использовать
null и nullable Nullable<T>, ?, null-условные операторы ?. и ??. Когда поле может быть пустым
Исключения try/catch/finally, создание собственных типов исключений, когда бросать, когда ловить
Дженерики List<T>, Dictionary<TKey,TValue>, собственные обобщённые методы и классы
LINQ .Where, .Select, .FirstOrDefault, .GroupBy, .ToDictionary — для обработки коллекций
ООП Классы, свойства, конструкторы, инкапсуляция, наследование, интерфейсы — на доменной модели
xUnit Написание unit-тестов: [Fact], [Theory], [InlineData], Assert.*
Git-база Коммиты с осмысленными сообщениями, ветки под задачи, merge

Технологии на M1

  • .NET 8, C# 12
  • CsvHelper (NuGet) для CSV
  • System.Text.Json (встроенный) для JSON
  • xUnit для тестов

Никаких фреймворков поверх — задача в том, чтобы написать парсер руками на фундаментальном C#.

Задание

Постановка

Построить парсер лабораторных данных, который:

  • принимает на вход файл (CSV или JSON) с результатами лабораторных испытаний;
  • превращает содержимое в граф доменных объектов с корректными связями по FK;
  • возвращает результат, в котором видны как успешно разобранные данные, так и некритичные проблемы;
  • корректно реагирует на критические ошибки (битый файл, отсутствие обязательных полей).

Входные данные

Лабораторные данные в одном из форматов:

  • CSV — «плоская» таблица. Колонки: идентификаторы образца, тип параметра, значение.
  • JSON — иерархическая структура (вложенные объекты).

Источники образцов и эталонных структур:

  • Swagger-ответы боевого стенда (эндпоинты по Sample, Sample_Lab, ParameterValue).
  • Справочники кодов параметров из docker/volumes/seeddata/...Dictionaries.xlsx (только для понимания того, какие коды параметров существуют).
  • Готовый файл-пример для тестирования — запросить у наставника, если Swagger-ответы недостаточны.

Сверка корректности полей модели — с домен-экспертом.

Выходные данные

Доменные объекты, корректно связанные по FK:

Project
  └─ Borehole (Borehole.ProjectId = Project.Id)
       └─ Sample (Sample.BoreholeId = Borehole.Id)
            └─ Sample_Lab (Sample_Lab.SampleId = Sample.Id)
                 └─ ParameterValue (ParameterValue.SampleLabId = Sample_Lab.Id)

Один файл на входе может содержать несколько выработок, образцов, параметров. Парсер строит полный граф объектов.

Требования к результату

Доменная модель

Создать классы для пяти агрегатов: Project, Borehole, Sample, Sample_Lab, ParameterValue. Состав полей каждого класса — самостоятельное решение, основанное на:

  • анализе Swagger-ответов стенда (какие поля реально есть);
  • сверке с домен-экспертом (какие поля обязательны, какие опциональны, какой смысл каждого).

DDM-конвенция команды (обязательная): связи между агрегатами — только через FK-поля. Навигационные свойства между агрегатами запрещены. Например, Sample ссылается на выработку через Guid BoreholeId, но не через свойство-объект Borehole Borehole. Это сознательная конвенция команды DeepGeo, и она соблюдается в проекте защиты с M1.

Парсер

Объявить интерфейс парсера и минимум две его реализации — для CSV и для JSON. Как именно выглядит интерфейс, какие методы содержит, какой тип возвращает — самостоятельное решение. Подсказка для размышления: что должен получить вызывающий код, если файл частично разобрался, но в нём были некритичные проблемы? Если просто бросать исключение — вызывающий потеряет часть данных. Если просто вернуть результат — вызывающий не поймёт, что были проблемы.

Обработка ошибок

Самостоятельно провести границу между:

  • критическими ошибками — файл невозможно разобрать, нарушены обязательные поля, битый формат → парсер не может продолжать;
  • некритичными проблемами — пропущено необязательное поле, неизвестный код параметра, дубликат → парсер может продолжать.

Для каждой категории выбрать свой механизм (исключение, предупреждение в результате, что-то ещё) и обосновать выбор. Не должно быть «тихих» ситуаций: либо ошибка бросается, либо фиксируется в результате.

Тесты (xUnit)

Тесты — обязательная часть M1. Без них веха не закрывается. Минимальный набор сценариев, которые нужно покрыть:

  • корректный вход → ожидаемый граф объектов;
  • пустой вход → корректная обработка;
  • файл с критической ошибкой (битый формат, отсутствует обязательное поле) → корректная обработка;
  • файл с некритичной проблемой (пропущено необязательное поле) → корректная обработка, данные не теряются;
  • согласованность FK в результате (на каждый Sample.BoreholeId существует Borehole.Id).

Формулировать конкретные тест-кейсы, имена тестов, набор утверждений — самостоятельная работа.

Инженерная культура

  • Регулярные коммиты с осмысленными сообщениями.
  • Ветки под отдельные задачи (например, feature/csv-parser, feature/json-parser, feature/tests отдельно).
  • README описывает, как собрать проект и запустить тесты.

Контрольные точки

В M1 — две контрольные точки с наставником:

Контрольная точка 1 (конец мес. 1)

  • Доменная модель создана, поля сверены с домен-экспертом.
  • Один из парсеров (CSV или JSON) работает на простом примере.
  • 3–5 базовых тестов проходят.
  • Git-история осмысленная, коммиты регулярные.

Контрольная точка 2 (конец мес. 2 = закрытие M1)

  • Оба парсера (CSV и JSON) работают.
  • Граф объектов корректен, FK согласованы.
  • Тесты покрывают happy path и основные ошибки.
  • Обработка ошибок осмысленная (критические vs некритичные).

Чек-лист завершения M1

  • Доменная модель: Project, Borehole, Sample, Sample_Lab, ParameterValue
  • Поля модели сверены с домен-экспертом
  • FK вместо навигационных свойств (соблюдение конвенции команды)
  • Интерфейс парсера + две реализации (CSV, JSON)
  • Корректная обработка критических и некритичных ошибок (с обоснованием границы)
  • Unit-тесты покрывают все ключевые сценарии
  • Все тесты проходят
  • Git-история: ветки под задачи, осмысленные коммиты
  • README описывает сборку и запуск тестов

Материалы по темам

Что изучить под задачи M1. Принцип: темы осваиваются по мере необходимости в парсере — потребовалось обработать коллекцию, изучил LINQ; упал null — разобрался с nullable-типами. Не нужно проходить Metanit «подряд».

C# — фундамент

ООП

Коллекции и LINQ

Работа с файлами и форматами

Тесты (xUnit)

Дополнительно (по мере необходимости)


Прогресс

[■■□□□] M1 из 5 вех — фундамент C# и парсер.

📚 Полный список ресурсов — в разделе Ресурсы.