- Зачем: - docs/internal/ превратился в свалку: дизайн-документы, ревью, планы и справочники лежали вперемешку. - архивные планы были неотличимы от живых документов. - Что: - docs/internal/ удалён; файлы распределены по docs/design/, docs/reference/, docs/archive/, docs/plans/, docs/assignment/. - educational-tasks.md убран из корня в архив (устарел). - обновлены все перекрёстные ссылки в AGENTS.md, TODO.md, README.md, docs/README.md и внутри design/reference/. - актуализированы architecture_review.md (статус DM-слоя), db_schema.md (DM-слой), TESTING.md, dag_execution_order.md, pxf_bookings.md. - добавлены заглушки docs/assignment/README.md и docs/plans/README.md. - Проверка: - make test && make lint - rg 'docs/internal' --glob '!docs/archive/*' — должно быть пусто.
7.8 KiB
Дизайн курсового задания
Тактические решения по нарезке задания, порядку выполнения и самопроверке. Стратегию и контекст см. в PRD.md.
1. Эталонный срез: витрина sales_report
Эталоном выбрана витрина dm.sales_report и вся её цепочка вниз по слоям.
Почему sales_report:
- Покрывает SCD1 (airports, tariffs), HWM-инкремент, fact load
- Богатая денормализация — хороший образец для подражания
- Средняя сложность — не пугает, но и не тривиальна
Эталонные таблицы (даны студенту)
| Слой | Таблицы |
|---|---|
| DM | sales_report |
| DDS | fact_flight_sales, dim_airports (SCD1), dim_tariffs (SCD1), dim_calendar |
| ODS | bookings, tickets, segments, flights, boarding_passes, airports |
| STG | bookings, tickets, segments, flights, boarding_passes, airports |
Задание студенту
| Слой | Таблицы | Что нового для студента |
|---|---|---|
| STG | airplanes, seats, routes |
Практика по аналогии с эталоном |
| ODS | airplanes, seats, routes |
Практика SCD1 UPSERT по аналогии |
| DDS | dim_airplanes (SCD1), dim_passengers (SCD1), dim_routes (SCD2) |
SCD2 — ключевой вызов курсовой |
| DM | airport_traffic, monthly_overview, route_performance, passenger_loyalty |
Разная сложность (от простой к сложной) |
2. Рекомендуемый порядок выполнения
Студенту рекомендуется (но не обязательно) двигаться в таком порядке:
- STG (airplanes, seats, routes) — разминка, по аналогии
- ODS (airplanes, seats, routes) — закрепление UPSERT
- DDS dim_airplanes, dim_passengers (SCD1) — новые измерения
- DDS dim_routes (SCD2) — ключевой вызов
- DM airport_traffic — простая витрина, похожа на sales_report
- DM route_performance — TRUNCATE+INSERT, SCD2-агрегация по BK
- DM monthly_overview — двухуровневая агрегация
- DM passenger_loyalty — самая сложная, пересчёт истории
Порядок выстроен от простого к сложному. Каждый шаг опирается на опыт предыдущего.
3. SCD2: подход «рецепт без готового SQL»
Реализация dim_routes (SCD2) — ключевой вызов курсовой. Студент делает это
самостоятельно, но ТЗ содержит пошаговую подсказку:
- Алгоритм SCD2 текстом (без SQL):
- Вычисли
hashdiffпо набору атрибутов (атрибуты перечислены в ТЗ) - Найди строки, у которых
hashdiffизменился - Закрой старую версию (
valid_to = текущая_дата) - Вставь новую версию (
valid_from = текущая_дата,valid_to = NULL)
- Вычисли
- Формула hashdiff:
md5(concat_ws('|', field1, field2, ...)) - Ссылка на
naming_conventions.md(поляvalid_from,valid_to,hashdiff) - Напоминание: полуоткрытый интервал
[valid_from, valid_to) - Если застрял — ветка
solution
Самостоятельная реализация — ключ к запоминанию. SCD2 — обязательный вопрос на собеседованиях DE, и студент должен уметь объяснить его на основе собственного опыта.
4. Валидационный DAG (bookings_validate)
Отдельный DAG для самопроверки студента. Запускается вручную в Airflow UI после реализации заданий. Таски сгруппированы по слоям — студент видит, где именно проблема. Дополнительный бонус — практика чтения логов Airflow.
Примерная структура тасков
bookings_validate
├── validate_stg
│ ├── check_stg_airplanes_exists (таблица создана, >0 строк)
│ ├── check_stg_seats_exists
│ └── check_stg_routes_exists
├── validate_ods
│ ├── check_ods_airplanes_rowcount (ODS >= STG по кол-ву уникальных BK)
│ ├── check_ods_seats_rowcount
│ ├── check_ods_routes_rowcount
│ └── check_ods_no_null_pks (PK not null)
├── validate_dds
│ ├── check_dim_airplanes_exists
│ ├── check_dim_passengers_exists
│ ├── check_dim_routes_scd2 (valid_from/valid_to корректны)
│ └── check_dim_routes_no_gaps (нет «дыр» в версиях SCD2)
└── validate_dm
├── check_airport_traffic_exists
├── check_monthly_overview_exists
├── check_route_performance_exists
└── check_passenger_loyalty_exists
Реализация
PostgresOperator+ SQL-скрипты вsql/validate/- Каждый SQL-скрипт выполняет SELECT и бросает исключение (через
DO $$ ... RAISE EXCEPTION ... $$), если проверка не пройдена - Сообщения об ошибках — дружелюбные, с подсказкой что делать дальше
Ключевые проверки
- Таблицы существуют и содержат данные
- PK не содержат NULL
- SCD2:
valid_to IS NULLдля текущих версий, нет перекрытий интервалов - Кросс-слойная консистентность (row count ODS vs STG)
- DM-витрины содержат данные за загруженные дни
5. Формат ТЗ от аналитика
Файл: docs/assignment/analyst_spec.md (или несколько файлов по слоям).
Для каждой таблицы-задания документ содержит:
- Имя таблицы и целевая схема (stg / ods / dds / dm)
- Описание — что хранит таблица, бизнес-смысл
- Список полей с типами и описанием
- Маппинг источников — откуда берётся каждое поле
- Бизнес-правила и фильтры (если есть)
- Тип историзации (SCD1 / SCD2 / snapshot / append)
- Гранулярность (одна строка = ?)
- Distribution key (подсказка или задание на выбор)
Формат — приближен к реальным ТЗ, которые студент встретит на работе.