Files
ddadminandClaude Opus 4.8 cc1cffe2f3 docs(course): каркас курса и переобвязка уроков 0–6 на путь import (#21)
Зачем: после редизайна пути менти курс ссылался на старый путь
generated-history-analytics/backfill и не проходился по новому стенду.

Что: в README курса — единый блок подготовки и канонического сброса
(make clean -> make up + ddl_init/world_init -> make superset-init),
таблица уроков дополнена лабами 07–08 («в работе»); LESSON_STANDARD и
уроки 0–6 ссылаются на канонический блок; урок 1 переведён на дозаливку
через world_next_day (кнопкой-анонсом, цена в минутах названа); урок 4 —
лесенка DAG-ов; урок 5 — словарь «база import / живой поток»; урок 6
обязателен; цифры старого мира помечены маркером «сверить-на-стенде».

Проверка: grep по generated-history-analytics/backfill в docs/course/
пуст; правки только в docs/course/; git diff --check чистый.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 13:22:41 +03:00

12 KiB
Raw Permalink Blame History

Стандарт уроков курса «Кликстрим на ClickHouse»

Дата: 2026-06-01. Поправка: 2026-06-05 (по итогам уроков 0–2 — добавлены §2 «Регистр и голос», описание шапки урока и §5 «Грабли, на которые мы уже наступили»). Назначение: рабочий чеклист, по которому пишется каждый урок. Открывается при создании урока. Рамка курса (зачем/что/скоуп) — в PRD.md; карта уроков и маршрут — в LEARNING_PLAN.md.


1. Шаблон урока

Каждый урок строится по единому шаблону:

  1. Зачем и где в проде — что за паттерн и где он встречается в обычной кликстрим-аналитике (без привязки к конкретной компании).
  2. Руки — что запустить и что понаблюдать (Kafka UI / ClickHouse / Grafana).
  3. Загляни внутрь — чтение отполированного эталонного кода с пояснениями.
  4. Управляемая правка — одно-два маленьких изменения с видимым результатом. Например: добавить поле в Materialized View и увидеть его в *_raw; «сломать» запись и увидеть +1 в таблице ошибок parse_errors; сменить kafka_group_name и увидеть, как топик читается заново. Менти меняет — видит эффект — объясняет. Верни как было — каждая правка завершается явным шагом отката к чистому состоянию (откатить изменение либо пройти канонический сброс), чтобы самостоятельный менти не застрял со сломанным стендом без ментора. (Урок 0 — без этого шага, только наблюдение.)
  5. Проверь себя — самопроверка (раздел 4).
  6. Что должно получитьсяконкретный видимый результат, который менти проверяет сам: скрин эффекта правки (например, красный DAG или +1 в таблице ошибок) плюс один абзац «своими словами» про паттерн урока или запрос, который пришлось написать. Это и есть самопроверка (раздел 4); те же вопросы «своими словами» менти разбирает с ментором на еженедельном созвоне. (Урок 0 — без правки, поэтому результат здесь — что менти увидел при наблюдении.)

Шапка урока

Кроме шести секций, каждый урок открывается единым блоком-цитатой (>) сверху — он задаёт рамку до того, как менти дойдёт до первой секции:

  • Формат: одной фразой, что менти делает, — **практика** — будешь сам запускать… или **наблюдение** — ничего не запускаем и не меняем…. Старые пометки «Статус: черновик» и «Режим: руки» не возвращаем: менти читал их как «материал не готов» и «непонятно, как понимать»;
  • Пререквизит: какой урок пройден и что менти уже умеет;
  • Эталонный путь: ссылка(и) на разбираемый файл;
  • Поток данных одной строкой: та же стрелочная схема, что стоит в начале эталонного файла;
  • О чём урок простыми словами: 1–2 фразы совсем простым языком, без терминов, — чтобы менти с первой строки понял, о чём речь.

В конце урока — короткий мост к следующему: какой честный вопрос остаётся открытым и как его закроет следующий урок.

2. Регистр и голос

Этот раздел — про то, как написан урок. Он появился по итогам уроков 0–2: мы начали со сжатого регистра и переписывали — дешевле сразу писать мягко.

Кто читатель. Менти прошёл курсовую, уровень — «обзорно» (понять идею и потрогать, а не стать экспертом). Поддержка — еженедельный созвон с ментором, а не «сессия»; на нём менти разбирает вопросы «своими словами».

Правила регистра:

  • термин расшифровываем на первом употреблении — коротко, своими словами (как ODS, DQ-split, Materialized View, *OrNull в уроках 1–2). Не оставляем слово голым;
  • человеческий тон, без жаргона ради жаргона — короткие предложения, прямое обращение к менти («открой», «посмотри», «помнишь из урока 0»);
  • ###-подзаголовки внутри длинных секций — особенно в «Загляни внутрь»: каждый смысловой кусок под своим заголовком, а не сплошной стеной;
  • плотные абзацы-«стены» бьём на пункты с конкретикой;
  • разжёвывать, а не сжимать. Урок может выйти заметно длиннее первого черновика — для «обзорно» это норма, а не повод резать.

House style (оставляем осознанно, ai-text-lint на это не правим): тире «—», буква «ё», жирные зачины абзацев, двоеточие перед списком.

Перед финалом — прогнать текст урока через /ai-text-lint (контекст article) и убрать настоящие AI-маркеры (например, слова вроде «ключевой», «является»), но house style выше не снимать.

3. Стандарт качества эталонного кода

Эталонные пути полируем до учебного качества; остальной код стенда остаётся под капотом — его не трогаем.

Чеклист (минимум). Файл доведён, если:

  1. комментарии на русском объясняют зачем, а не пересказывают код;
  2. шаги явные и названы своими именами, без неочевидных трюков;
  3. в начале файла — поток данных одной строкой (как в STG: Kafka → kafka_*_raw → MV → *_raw);
  4. ошибки и проверки качества данных видны — понятно, куда смотреть;
  5. нет мусора: мёртвого кода, закомментированных экспериментов, разнобоя в именах.

Тест одного прохода (главный критерий и защита от громоздкости).

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

Если тест не проходит — правим строго одним из трёх способов: (1) упростить код; (2) добавить ровно одну строку «зачем» там, где код честно неочевиден; (3) убрать лишнее под капот или в короткую пометку. Добавить ещё комментариев — не способ.

Две защиты от раздувания:

  • комментируем только неочевидное «зачем» (очевидную строку комментировать нельзя — лишний текст сам по себе мешает понимать);
  • «близко к проду» ≠ «вся прод-сложность прямо в коде урока»: один прод-паттерн на урок показываем чисто, остальные прод-заботы — короткой пометкой «в проде иначе: …».

Вердикты аудита по конкретным путям — в LEARNING_PLAN.md.

4. Самопроверка (по-простому)

Отдельный тест-фреймворк не строим. Опираемся на то, что в стенде уже есть:

  • штатные быстрые проверки (smoke) из docs/TEST_PLAN.md;
  • встроенные проверки в etl_pipeline_dag.py (DAG падает на пустой витрине или нарушении целостности);
  • канонический сброс для чистого возврата и повтора штатного пути.

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

5. Грабли, на которые мы уже наступили

Короткий список ошибок из уроков 0–2 — чтобы следующий урок их не повторил.

  • Проверяй на стенде, а не «на глаз». Любой категоричный claim про числа или целостность подтверждай командой на стенде. Так нашёлся баг с kafka_ts в уроке 1 (значение типа DateTime64 молча резалось через toInt64, и время по всему стенду уехало в 1970) и подтвердилось, что меньший размер таблиц контекста в уроке 2 — это схлопывание повторов по click_id (проверяется через uniqExact), а не потеря данных.
  • Имена таблиц и колонок в тексте сверяй с реальным DDL. То, что написано в уроке, должно совпадать с sql/ddl/..., иначе менти запутается, когда выполнит запрос на стенде.
  • Один паттерн на урок; будущие темы только анонсируй. Не раскрывай то, что относится к следующим урокам (пример: жёсткий гейт на «сирот» — это урок 4, в уроке 3 мы их только вводим как понятие).
  • Спорные API ClickHouse сверяй через MCP Context7 (зачем и в каком порядке — в AGENTS.md), не полагайся на память: именно типы и поведение функций уже один раз подвели.