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) для CSVSystem.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# — фундамент
- metanit.com — Переменные и типы данных
- metanit.com — Nullable-типы
- metanit.com — Управляющие конструкции
- metanit.com — Исключения
- metanit.com — Методы
ООП
- metanit.com — Классы и объекты
- metanit.com — Конструкторы
- metanit.com — Свойства
- metanit.com — Модификаторы доступа
- metanit.com — Наследование
- metanit.com — Виртуальные методы и полиморфизм
- metanit.com — Интерфейсы
- metanit.com — Обобщения (дженерики)
Коллекции и LINQ
Работа с файлами и форматами
- metanit.com — Работа с файловой системой
- CsvHelper — документация — как читать CSV.
- Microsoft Learn — System.Text.Json (RU) — как парсить JSON.
Тесты (xUnit)
- xUnit — документация — основы:
[Fact],[Theory],Assert.*. - metanit.com — Тестирование xUnit (RU) — примеры на русском.
Дополнительно (по мере необходимости)
- Microsoft Learn — C# (RU) — официальная справка.
Прогресс
[■■□□□] M1 из 5 вех — фундамент C# и парсер.
- ⬅️ M0 — старт
- ➡️ M2 — персистентность — сохранение данных в PostgreSQL
- 🐛 QA-трек — параллельный поток работы с багами
- ✅ Чек-листы — критерии прохождения вех
📚 Полный список ресурсов — в разделе Ресурсы.