Лабораторная работа 1. Моделирование предметной области¶
Об этом материале
Кода в этой работе нет. Прикладной код начинается со второй лабораторной. Сдаётся: документы и диаграммы в docs/, скелет решения с зелёной сборкой. Оценка: 40 баллов. Ветка lab-01, отдельный pull request.
В этой работе не пишется прикладной код. Совсем. Вы разбираетесь, что именно предстоит построить, и фиксируете понимание так, чтобы его можно было проверить и оспорить. Всё, что вы здесь напишете, доживёт до защиты: глоссарий станет именами классов, список событий — методами, диаграмма состояний — тестами. Работа рассчитана на две аудиторные пары плюс домашнюю часть.
Цель¶
Построить модель предметной области HR-системы на языке заказчика и обосновать границы будущей системы до того, как появится первая строка кода.
Отдельная цель, менее очевидная: убедиться, что о системе можно рассуждать содержательно, не назвав ни одной технологии. Всё, что вы решите в этой работе, останется верным независимо от того, чем вы потом будете хранить и передавать данные.
Что нужно иметь под рукой¶
Техническое задание на проект — разделы 3, 4, 5, 6, 7, 8 и 14. Дальше ссылки идут
по номерам требований оттуда: FR-14, BR-07 и так далее.
Ход аудиторной части (две пары)¶
Первая пара — от текста задания к событиям.
- Разбор ТЗ: читаем разделы 1–4, выписываем непонятное
- Индивидуально выписываем доменные события
- Раскладываем события по временной оси, снимаем дубли
- К каждому событию находим команду и её инициатора
Вторая пара — от событий к границам.
- Группируем события в кластеры, ищем границы
- Отмечаем горячие точки — места, где нет ответа
- Диаграмма состояний кандидатуры
- Разбор расхождений между вариантами
Работаем на доске или на стикерах, ноутбук закрыт. Перенос в текст — дома. Это не педантизм: как только открывается IDE, моделирование незаметно превращается в набор классов, а вопросы, которые надо было задать, остаются незаданными.
Дальше разобрано то, что чаще всего идёт не так. Требования к диаграмме состояний — в разделе «Что сдаётся».
Разбор ТЗ¶
Читаем разделы 1–4 и выписываем всё, что непонятно или вызывает сомнение. Задача этого этапа — не понять задание, а обнаружить места, где вы его понимаете иначе, чем сосед. Такие места чаще всего и оказываются настоящими проектными решениями.
Доменные события¶
Событие — это факт, который уже произошёл и который важен бизнесу. Пишется в прошедшем времени и на языке предметной области: так, как об этом сказал бы рекрутер.
Правильно: ВакансияОпубликована, ОткликПодан, КандидатураОтклонена,
СрокОффераИстёк, РольОтозвана.
Неправильно: СозданиеВакансии — это не факт, а действие, которое ещё может
не состояться. ДанныеОбновлены — рекрутер так не скажет, значит это не событие
предметной области. UpdateApplicationStatus — это имя метода, а не факт.
Целевой ориентир — не менее двадцати пяти событий. Если получилось десять, вы описали только счастливый путь: вернитесь к разделам 5.4, 5.5 и 5.7 ТЗ и посмотрите, что происходит с уведомлениями, тестовыми заданиями, ролями и назначениями.
Проверьте, что среди ваших событий есть такие, которые никто не инициировал: истечение срока оффера — это факт без человека за ним. Такие события легко пропустить, а они определяют, понадобится ли системе фоновая обработка.
Когда события выписаны, разложите их слева направо в том порядке, в каком они случаются в жизни. На этом шаге всплывает половина ошибок: обнаруживаются дубли, названные по-разному, события, которые невозможно расположить однозначно, и разрывы — места, где между двумя фактами явно чего-то не хватает.
Команды и инициаторы¶
Для каждого события ответьте на два вопроса: какая команда к нему привела и кто эту команду отдал. Инициатором может быть кандидат, сотрудник в определённой роли, внешняя система или время.
| Команда | Инициатор | Событие |
|---|---|---|
Опубликовать вакансию |
Рекрутер | ВакансияОпубликована |
Откликнуться |
Кандидат | ОткликПодан |
Продвинуть кандидатуру |
Исполнитель текущего этапа | КандидатураПродвинута |
— |
Время | СрокОффераИстёк |
Тройки, где в колонке команды стоит прочерк, — самые интересные. Их разбираем отдельно.
Кластеры и границы¶
Сгруппируйте события по тому, что именно меняется в момент их возникновения. События, меняющие одно и то же, скорее всего относятся к одному понятию.
Дальше ответьте на вопросы, вокруг которых и строится вся работа:
- Какие данные обязаны меняться одной неделимой операцией, чтобы правило не нарушилось?
- Какие данные могут расходиться на секунду-другую без вреда для бизнеса?
- Где проходит граница, за которой достаточно хранить только идентификатор, а не сам объект?
Пример для размышления: BR-03 требует, чтобы кандидатура двигалась строго по этапам
своего пайплайна. Значит, проверить это правило можно, только имея под рукой и текущий
этап, и пайплайн. Означает ли это, что вакансия и кандидатура — одно целое? Ответ
не «да» и не «нет», а BR-07, который вы должны прочитать заново именно сейчас.
Горячие точки¶
Отмечайте всё, что вызвало спор или где ТЗ молчит. Раздел 14 ТЗ содержит тринадцать вопросов, на которые заказчик намеренно не дал ответа, — но ваш список не обязан ими ограничиваться. Хорошие горячие точки, найденные самостоятельно, оцениваются отдельно.
В конце второй пары сравниваем результаты вслух. Интересны не совпадения, а места, где две модели одной и той же системы разошлись: почти всегда за расхождением стоит разное прочтение одного и того же требования.
Что сдаётся¶
Всё — текстом в репозитории проекта, который создаётся автоматически при регистрации
на курс в организации github.com/radilov-spsu.
Работа оформляется отдельным pull request'ом из ветки lab-01 и вливается только
после ревью и одобрения преподавателем.
Диаграммы только на Mermaid. Картинки, вставленные скриншотом, не принимаются: их нельзя ни отревьюить, ни изменить.
docs/
├── glossary.md 15–20 терминов предметной области
├── events.md события, команды, инициаторы
├── boundaries.md кластеры, предполагаемые границы, обоснование
├── open-questions.md ответы на вопросы раздела 14 ТЗ
├── adr/
│ ├── 0000-stack.md выбранный язык и почему (если не .NET)
│ └── 0001-layers.md почему слоёв столько, сколько есть
└── diagrams/
├── context.mmd система и её внешнее окружение
├── hiring-process.mmd процесс найма от публикации до найма
└── candidacy-states.mmd состояния кандидатуры
src/ четыре пустых модуля с зависимостями
tests/
README.md
Глоссарий¶
От 15 до 20 терминов. У каждого — определение одним предложением.
Проверка каждого определения одна: прочитайте его вслух так, как будто перед вами
руководитель отдела подбора. Он должен кивнуть. Если в определении встречаются слова
из словаря программиста — класс, объект, сущность, поле, запись,
идентификатор, список, — а также суффиксы Manager, Service, Helper, Info,
Data, определение написано не на том языке и переписывается.
Термины из ТЗ можно взять за основу, но не копировать целиком: минимум пять терминов должны быть вашими, найденными при разборе. Если вы уточнили или оспорили определение из ТЗ — отметьте это, такие уточнения ценятся.
События¶
Не менее двадцати пяти событий с командами и инициаторами. Отдельным списком — события без инициатора-человека.
Границы¶
Перечислите понятия, которые вы считаете самостоятельными, и для каждого укажите:
какие события его меняют, какие правила оно обязано защищать, на что оно ссылается
только по идентификатору. Обоснуйте, почему граница проходит именно там: аргумент
«так удобнее» не принимается, аргумент «иначе нарушится BR-xx» принимается.
Диаграмма состояний¶
Все состояния кандидатуры, все переходы с условиями, явно обозначенные начальное и терминальные состояния. Обязательно покажите, чем состояние отличается от текущего этапа пайплайна: это разные измерения, и диаграмма должна это отражать.
Ответы на открытые вопросы¶
Пять вопросов из раздела 14 ТЗ. Три обязательных: 2 (граница между вакансией и кандидатурой), 3 (фиксация пайплайна) и 9 (граница между снимком и живой ссылкой при работе с ролями). Ещё два — на выбор.
Ответ — это позиция плюс цена. По абзацу на каждый вопрос: что вы решили, какую альтернативу отвергли и чем платите за свой выбор. Ответ без второй части считается отсутствующим.
Скелет решения¶
Четыре единицы сборки из блока 8 лекции 1 — домен, сценарии, инфраструктура, веб — с расставленными зависимостями. Сборка проходит. Проверка: попытка сделать домен зависимым от инфраструктуры ломает сборку либо падает в проверяющем инструменте.
Модули пустые — ни одного пакета, ни одного класса. Инфраструктура на этом этапе не содержит ничего, кроме имени: чем именно она будет заполнена, решается не сейчас.
Стек — на ваш выбор, но выбранный не по умолчанию согласуется со мной и фиксируется
в docs/adr/0000-stack.md. Примеры на занятиях будут на C#; на структуру вашего
проекта это не влияет.
ADR¶
Одна запись по шаблону:
# 0001. Число слоёв в решении
## Статус
Принято, 2026-09-08
## Контекст
Что за задача, какие силы действуют, чем ограничены.
## Решение
Что именно решили. В настоящем времени: «Выделяем четыре слоя…».
## Альтернативы
Что ещё рассматривали и почему отвергли.
## Последствия
Что стало проще, что усложнилось, за что придётся платить.
Раздел «Альтернативы» — обязательный. ADR без него превращается в пересказ того, что и так видно в коде.
Критерии оценки¶
| Что оценивается | Баллов |
|---|---|
| Глоссарий: полнота, язык предметной области, собственные термины | 4 |
| События: количество, формулировки, события без инициатора | 5 |
| Команды и инициаторы, согласованные с ролями из ТЗ | 3 |
Границы: обоснование через конкретные правила BR-xx |
6 |
| Диаграмма состояний: терминальные состояния, разделение статуса и этапа | 4 |
| Диаграммы контекста и процесса | 3 |
| Ответы на открытые вопросы: позиция плюс цена | 6 |
| Скелет решения, ссылки, зелёная сборка | 3 |
| ADR с разделом альтернатив | 3 |
| Самостоятельно найденные горячие точки | до 3 |
| Итого | 40 |
Работа не принимается, если диаграммы приложены картинками, если ответы на открытые вопросы не содержат отвергнутых альтернатив или если в глоссарии присутствуют запрещённые слова.
Типичные ошибки¶
Глоссарий на языке программиста. Признак — термины вида ApplicationEntity,
VacancyModel, определения через «объект, содержащий поля». Проверьте себя вслух:
руководитель отдела подбора должен согласиться с каждым определением, не переспрашивая.
События в настоящем времени. СозданиеОтклика — это действие, которое ещё может
не состояться. ОткликПодан — факт, который уже произошёл и который нельзя отменить,
можно только компенсировать другим событием. Разница определит, как вы будете
проектировать историю решений (BR-10).
Только счастливый путь. Отклонения, истечения сроков, отзывы ролей, повторные доставки вебхука — это не «исключительные ситуации», а половина системы. Проверьте, что среди ваших событий есть хотя бы пять неприятных.
Статус и этап слиты в одно. Соблазн сделать один перечислимый тип со значениями
Скрининг, Тестовое, Отклонён, Нанят велик и убивает всю модель: этапы
у каждой вакансии свои, а статусы одинаковы для всей системы. Раздел 7 ТЗ говорит
об этом прямо.
Роли из головы, а не из ТЗ. Появляется «HR-менеджер», который делает всё. В ТЗ две независимые системы ролей и назначения на этап; если вашей модели они не видны, вы решаете не ту задачу.
Русские имена в коде. В скелете решения имена модулей, файлов, веток — только английские. По-русски пишутся комментарии, документы и, если хотите, сообщения коммитов.
Ответы вида «сделаю как будет удобнее». Это не ответ. Вопросы раздела 14 не имеют единственно верного решения, но каждый из них имеет цену, и вас спросят именно про неё.
Вопросы на защите¶
Отвечаете устно, глядя в свои же документы.
- Покажите событие, у которого нет инициатора-человека. Что в системе должно существовать, чтобы оно вообще случилось?
- Возьмите правило
BR-03. Какие данные должны быть доступны одновременно, чтобы его проверить? - Вы провели границу между вакансией и кандидатурой вот здесь. Что сломается, если провести её на шаг левее?
BR-07требует зафиксировать пайплайн,BR-18— вычислять обладателей роли каждый раз. Почему заказчик хочет по-разному?- Какое из ваших состояний терминально и как вы это гарантируете, кроме как «мы не будем вызывать этот метод»?
- Назовите термин, который вы добавили сами. Почему его не хватало?
- В вашем ADR отвергнута альтернатива. Что должно измениться в требованиях, чтобы вы выбрали её?
Шпаргалка по Mermaid¶
Диаграмма состояний:
Диаграмма процесса:
flowchart LR
A["Рекрутер публикует"] --> B{"Есть назначения<br/>на всех этапах?"}
B -->|нет| A
B -->|да| C["Вакансия видна"]
Файлы с расширением .mmd подсвечиваются и отображаются прямо в GitHub, отдельных
инструментов не требуется. Для проверки локально — расширение Mermaid для VS Code.
Что дальше¶
Ко второй лабораторной вы вернётесь к этим файлам и обнаружите, что часть решений была неверной. Это нормально и ожидаемо: модель уточняется, когда встречается с кодом. Важно другое — фиксировать изменения. Каждое расхождение между тем, что вы написали сейчас, и тем, что окажется в коде, должно попасть в новый ADR с объяснением, что именно вы поняли не так.
Модель, которую ни разу не поправили за семестр, — это модель, которую не проверяли реальностью.